From 4d30a1e4f1edecff86d5066ce4653a370e59e5e1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 30 Jan 2008 08:01:00 -0800 Subject: Version abc80130 --- Makefile | 26 +- abc.dsp | 1508 +--- abc.rc | 89 +- abclib.dsp | 2844 -------- abclib.dsw | 29 - abctestlib.dsp | 102 - abctestlib.dsw | 29 - copyright.txt | 18 - demo.c | 181 - graph_lib.txt | 1407 ++++ readme | 26 - regtest.script | 119 +- regtest_output.txt | 241 +- src/abc8/aig/aig.h | 619 ++ src/abc8/aig/aigCheck.c | 163 + src/abc8/aig/aigCuts.c | 669 ++ src/abc8/aig/aigDfs.c | 723 ++ src/abc8/aig/aigFanout.c | 189 + src/abc8/aig/aigFrames.c | 133 + src/abc8/aig/aigHaig.c | 270 + src/abc8/aig/aigInter.c | 174 + src/abc8/aig/aigMan.c | 369 + src/abc8/aig/aigMem.c | 598 ++ src/abc8/aig/aigMffc.c | 297 + src/abc8/aig/aigObj.c | 431 ++ src/abc8/aig/aigOper.c | 541 ++ src/abc8/aig/aigOrder.c | 171 + src/abc8/aig/aigPart.c | 992 +++ src/abc8/aig/aigRepr.c | 457 ++ src/abc8/aig/aigRet.c | 969 +++ src/abc8/aig/aigRetF.c | 219 + src/abc8/aig/aigScl.c | 399 ++ src/abc8/aig/aigSeq.c | 502 ++ src/abc8/aig/aigShow.c | 356 + src/abc8/aig/aigTable.c | 289 + src/abc8/aig/aigTiming.c | 351 + src/abc8/aig/aigTruth.c | 98 + src/abc8/aig/aigTsim.c | 436 ++ src/abc8/aig/aigUtil.c | 855 +++ src/abc8/aig/aigWin.c | 184 + src/abc8/aig/aig_.c | 48 + src/abc8/aig/module.make | 23 + src/abc8/bsat/module.make | 6 + src/abc8/bsat/satInter.c | 991 +++ src/abc8/bsat/satInterA.c | 970 +++ src/abc8/bsat/satMem.c | 527 ++ src/abc8/bsat/satMem.h | 80 + src/abc8/bsat/satSolver.c | 1358 ++++ src/abc8/bsat/satSolver.h | 210 + src/abc8/bsat/satStore.c | 437 ++ src/abc8/bsat/satStore.h | 146 + src/abc8/bsat/satTrace.c | 109 + src/abc8/bsat/satUtil.c | 234 + src/abc8/bsat/satVec.h | 83 + src/abc8/cnf/cnf.h | 163 + src/abc8/cnf/cnfCore.c | 185 + src/abc8/cnf/cnfCut.c | 371 + src/abc8/cnf/cnfData.c | 4784 +++++++++++++ src/abc8/cnf/cnfMan.c | 282 + src/abc8/cnf/cnfMap.c | 356 + src/abc8/cnf/cnfPost.c | 233 + src/abc8/cnf/cnfUtil.c | 188 + src/abc8/cnf/cnfWrite.c | 447 ++ src/abc8/cnf/cnf_.c | 48 + src/abc8/cnf/module.make | 8 + src/abc8/dar/dar.h | 106 + src/abc8/dar/darBalance.c | 400 ++ src/abc8/dar/darCore.c | 289 + src/abc8/dar/darCut.c | 739 ++ src/abc8/dar/darData.c | 11287 +++++++++++++++++++++++++++++ src/abc8/dar/darInt.h | 166 + src/abc8/dar/darLib.c | 980 +++ src/abc8/dar/darMan.c | 133 + src/abc8/dar/darPrec.c | 387 + src/abc8/dar/darRefact.c | 591 ++ src/abc8/dar/darResub.c | 48 + src/abc8/dar/darScript.c | 393 + src/abc8/dar/dar_.c | 48 + src/abc8/dar/module.make | 10 + src/abc8/fra/fra.h | 324 + src/abc8/fra/fraBmc.c | 422 ++ src/abc8/fra/fraCec.c | 303 + src/abc8/fra/fraClass.c | 855 +++ src/abc8/fra/fraClau.c | 759 ++ src/abc8/fra/fraClaus.c | 1766 +++++ src/abc8/fra/fraCnf.c | 284 + src/abc8/fra/fraCore.c | 466 ++ src/abc8/fra/fraImp.c | 723 ++ src/abc8/fra/fraInd.c | 484 ++ src/abc8/fra/fraLcr.c | 656 ++ src/abc8/fra/fraMan.c | 304 + src/abc8/fra/fraPart.c | 263 + src/abc8/fra/fraSat.c | 452 ++ src/abc8/fra/fraSec.c | 290 + src/abc8/fra/fraSim.c | 1066 +++ src/abc8/fra/fra_.c | 48 + src/abc8/fra/module.make | 15 + src/abc8/ioa/ioa.h | 80 + src/abc8/ioa/ioaReadAig.c | 366 + src/abc8/ioa/ioaUtil.c | 117 + src/abc8/ioa/ioaWriteAig.c | 378 + src/abc8/ioa/module.make | 3 + src/abc8/kit/cloud.c | 987 +++ src/abc8/kit/cloud.h | 269 + src/abc8/kit/kit.h | 596 ++ src/abc8/kit/kitAig.c | 121 + src/abc8/kit/kitBdd.c | 231 + src/abc8/kit/kitCloud.c | 368 + src/abc8/kit/kitDsd.c | 2621 +++++++ src/abc8/kit/kitFactor.c | 339 + src/abc8/kit/kitGraph.c | 397 ++ src/abc8/kit/kitHop.c | 144 + src/abc8/kit/kitIsop.c | 325 + src/abc8/kit/kitSop.c | 572 ++ src/abc8/kit/kitTruth.c | 1721 +++++ src/abc8/kit/kit_.c | 48 + src/abc8/kit/module.make | 8 + src/abc8/vec2/module.make | 1 + src/abc8/vec2/vec2.h | 121 + src/abc8/vec2/vecAtt.h | 391 + src/abc8/vec2/vecFlt.h | 630 ++ src/abc8/vec2/vecInt.h | 834 +++ src/abc8/vec2/vecPtr.h | 812 +++ src/abc8/vec2/vecStr.h | 583 ++ src/abc8/vec2/vecVec.h | 356 + src/aig/aig/aig.h | 619 -- src/aig/aig/aigCheck.c | 163 - src/aig/aig/aigCuts.c | 669 -- src/aig/aig/aigDfs.c | 723 -- src/aig/aig/aigFanout.c | 189 - src/aig/aig/aigFrames.c | 133 - src/aig/aig/aigHaig.c | 270 - src/aig/aig/aigInter.c | 174 - src/aig/aig/aigMan.c | 369 - src/aig/aig/aigMem.c | 598 -- src/aig/aig/aigMffc.c | 297 - src/aig/aig/aigObj.c | 431 -- src/aig/aig/aigOper.c | 541 -- src/aig/aig/aigOrder.c | 171 - src/aig/aig/aigPart.c | 992 --- src/aig/aig/aigRepr.c | 457 -- src/aig/aig/aigRet.c | 969 --- src/aig/aig/aigRetF.c | 219 - src/aig/aig/aigScl.c | 399 -- src/aig/aig/aigSeq.c | 502 -- src/aig/aig/aigShow.c | 356 - src/aig/aig/aigTable.c | 289 - src/aig/aig/aigTiming.c | 351 - src/aig/aig/aigTruth.c | 98 - src/aig/aig/aigTsim.c | 436 -- src/aig/aig/aigUtil.c | 855 --- src/aig/aig/aigWin.c | 184 - src/aig/aig/aig_.c | 48 - src/aig/aig/module.make | 25 - 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 | 163 - src/aig/cnf/cnfCore.c | 185 - src/aig/cnf/cnfCut.c | 371 - src/aig/cnf/cnfData.c | 4784 ------------- src/aig/cnf/cnfMan.c | 282 - src/aig/cnf/cnfMap.c | 356 - src/aig/cnf/cnfPost.c | 233 - src/aig/cnf/cnfUtil.c | 188 - src/aig/cnf/cnfWrite.c | 445 -- 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 | 106 - src/aig/dar/darBalance.c | 400 -- src/aig/dar/darCore.c | 289 - src/aig/dar/darCut.c | 739 -- src/aig/dar/darData.c | 11287 ----------------------------- src/aig/dar/darInt.h | 166 - src/aig/dar/darLib.c | 980 --- src/aig/dar/darMan.c | 133 - src/aig/dar/darPrec.c | 387 - src/aig/dar/darRefact.c | 591 -- src/aig/dar/darResub.c | 48 - src/aig/dar/darScript.c | 393 - src/aig/dar/dar_.c | 48 - src/aig/dar/module.make | 10 - src/aig/deco/deco.h | 703 -- src/aig/deco/module.make | 1 - src/aig/fra/fra.h | 324 - src/aig/fra/fraBmc.c | 422 -- src/aig/fra/fraCec.c | 303 - src/aig/fra/fraClass.c | 855 --- src/aig/fra/fraClau.c | 759 -- src/aig/fra/fraClaus.c | 1561 ---- src/aig/fra/fraCnf.c | 284 - src/aig/fra/fraCore.c | 466 -- src/aig/fra/fraImp.c | 723 -- src/aig/fra/fraInd.c | 484 -- src/aig/fra/fraLcr.c | 656 -- src/aig/fra/fraMan.c | 304 - src/aig/fra/fraPart.c | 263 - src/aig/fra/fraSat.c | 452 -- src/aig/fra/fraSec.c | 290 - src/aig/fra/fraSim.c | 1066 --- src/aig/fra/fra_.c | 48 - src/aig/fra/module.make | 15 - 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 | 366 - src/aig/ioa/ioaUtil.c | 117 - src/aig/ioa/ioaWriteAig.c | 378 - 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 | 2760 ------- 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 | 339 - src/aig/kit/kitGraph.c | 397 -- src/aig/kit/kitHop.c | 144 - src/aig/kit/kitIsop.c | 325 - src/aig/kit/kitSop.c | 572 -- src/aig/kit/kitTruth.c | 1721 ----- 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/ntl/module.make | 11 - src/aig/ntl/ntl.h | 277 - src/aig/ntl/ntlAig.c | 596 -- src/aig/ntl/ntlCheck.c | 126 - src/aig/ntl/ntlDfs.c | 184 - src/aig/ntl/ntlMan.c | 196 - src/aig/ntl/ntlMap.c | 624 -- src/aig/ntl/ntlObj.c | 238 - src/aig/ntl/ntlReadBlif.c | 1163 --- src/aig/ntl/ntlTable.c | 217 - src/aig/ntl/ntlTime.c | 128 - src/aig/ntl/ntlWriteBlif.c | 127 - src/aig/ntl/ntl_.c | 47 - 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/aig/tim/module.make | 1 - src/aig/tim/tim.c | 532 -- src/aig/tim/tim.h | 85 - src/base/abc/1.txt | 21 - src/base/abc/abc.h | 880 +-- src/base/abc/abcAig.c | 769 +- src/base/abc/abcBlifMv.c | 970 --- src/base/abc/abcCheck.c | 442 +- src/base/abc/abcDfs.c | 1057 +-- src/base/abc/abcFanio.c | 167 +- src/base/abc/abcFunc.c | 781 +- src/base/abc/abcHie.c | 492 -- src/base/abc/abcInt.h | 10 +- src/base/abc/abcLatch.c | 238 +- src/base/abc/abcLib.c | 454 -- src/base/abc/abcMinBase.c | 288 +- src/base/abc/abcNames.c | 366 +- src/base/abc/abcNetlist.c | 201 +- src/base/abc/abcNtk.c | 970 +-- src/base/abc/abcObj.c | 817 +-- src/base/abc/abcRefs.c | 310 +- src/base/abc/abcShow.c | 100 +- src/base/abc/abcSop.c | 470 +- src/base/abc/abcUtil.c | 1314 +--- src/base/abc/abc_.c | 2 +- src/base/abc/module.make | 3 - src/base/abci/abc.c | 13062 +++++----------------------------- src/base/abci/abcAttach.c | 12 +- src/base/abci/abcAuto.c | 239 - src/base/abci/abcBalance.c | 427 +- src/base/abci/abcBmc.c | 115 - src/base/abci/abcCas.c | 111 - src/base/abci/abcClpBdd.c | 181 - src/base/abci/abcClpSop.c | 53 - src/base/abci/abcCollapse.c | 146 + src/base/abci/abcCut.c | 494 +- src/base/abci/abcDar.c | 1252 +--- src/base/abci/abcDebug.c | 208 - src/base/abci/abcDress.c | 209 - src/base/abci/abcDsd.c | 102 +- src/base/abci/abcEspresso.c | 250 - src/base/abci/abcExtract.c | 51 - src/base/abci/abcFpga.c | 44 +- src/base/abci/abcFpgaFast.c | 190 - src/base/abci/abcFraig.c | 446 +- src/base/abci/abcFxu.c | 19 +- src/base/abci/abcGen.c | 511 -- src/base/abci/abcHaig.c | 179 +- src/base/abci/abcIf.c | 497 -- src/base/abci/abcIvy.c | 1105 --- src/base/abci/abcLut.c | 786 -- src/base/abci/abcMap.c | 100 +- src/base/abci/abcMeasure.c | 478 -- src/base/abci/abcMini.c | 153 - src/base/abci/abcMiter.c | 778 +- src/base/abci/abcMulti.c | 643 -- src/base/abci/abcMv.c | 369 - src/base/abci/abcNtbdd.c | 389 +- src/base/abci/abcOdc.c | 1134 --- src/base/abci/abcOrder.c | 131 - src/base/abci/abcPart.c | 890 +-- src/base/abci/abcPlace.c | 255 - src/base/abci/abcPrint.c | 536 +- src/base/abci/abcProve.c | 341 - src/base/abci/abcQbf.c | 260 - src/base/abci/abcQuant.c | 419 -- src/base/abci/abcRec.c | 1173 --- src/base/abci/abcReconv.c | 32 +- src/base/abci/abcRefactor.c | 51 +- src/base/abci/abcRenode.c | 651 +- src/base/abci/abcReorder.c | 102 - src/base/abci/abcRestruct.c | 1497 ---- src/base/abci/abcResub.c | 1952 ----- src/base/abci/abcRewrite.c | 281 +- src/base/abci/abcRr.c | 999 --- src/base/abci/abcSat.c | 776 +- src/base/abci/abcStrash.c | 441 +- src/base/abci/abcSweep.c | 586 +- src/base/abci/abcSymm.c | 29 +- src/base/abci/abcTiming.c | 250 +- src/base/abci/abcUnate.c | 155 - src/base/abci/abcUnreach.c | 70 +- src/base/abci/abcVerify.c | 817 +-- src/base/abci/abcXsim.c | 224 - src/base/abci/abc_.c | 5 +- src/base/abci/abc_new.h | 23 - src/base/abci/module.make | 34 +- src/base/abcs/abcRetime.c | 203 + src/base/abcs/abcSeq.c | 642 ++ src/base/abcs/abc_.c | 47 + src/base/abcs/module.make | 2 + src/base/cmd/cmd.c | 360 +- src/base/cmd/cmd.h | 16 +- src/base/cmd/cmdAlias.c | 6 +- src/base/cmd/cmdApi.c | 6 +- src/base/cmd/cmdFlag.c | 9 +- src/base/cmd/cmdHist.c | 6 +- src/base/cmd/cmdInt.h | 4 +- src/base/cmd/cmdUtils.c | 30 +- src/base/io/io.c | 1757 ++--- src/base/io/io.h | 110 +- src/base/io/ioInt.h | 6 +- src/base/io/ioRead.c | 81 + src/base/io/ioReadAiger.c | 366 - src/base/io/ioReadBaf.c | 171 - src/base/io/ioReadBench.c | 223 +- src/base/io/ioReadBlif.c | 772 +- src/base/io/ioReadBlifAig.c | 1013 --- src/base/io/ioReadBlifMv.c | 1702 ----- src/base/io/ioReadDsd.c | 308 - src/base/io/ioReadEdif.c | 17 +- src/base/io/ioReadEqn.c | 73 +- src/base/io/ioReadPla.c | 7 +- src/base/io/ioReadVerilog.c | 727 +- src/base/io/ioUtil.c | 571 +- src/base/io/ioWriteAiger.c | 375 - src/base/io/ioWriteBaf.c | 168 - src/base/io/ioWriteBench.c | 188 +- src/base/io/ioWriteBlif.c | 173 +- src/base/io/ioWriteBlifMv.c | 519 -- src/base/io/ioWriteCnf.c | 65 +- src/base/io/ioWriteDot.c | 572 +- src/base/io/ioWriteEqn.c | 117 +- src/base/io/ioWriteGml.c | 2 +- src/base/io/ioWriteList.c | 288 - src/base/io/ioWritePla.c | 23 +- src/base/io/ioWriteVerilog.c | 639 -- src/base/io/io_.c | 48 - src/base/io/module.make | 13 +- src/base/main/libSupport.c | 193 - src/base/main/main.c | 107 +- src/base/main/main.h | 40 +- src/base/main/mainFrame.c | 62 +- src/base/main/mainInit.c | 8 +- src/base/main/mainInt.h | 16 +- src/base/main/mainUtils.c | 91 +- src/base/main/module.make | 1 - 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 | 493 -- 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 | 2949 -------- src/base/ver/verFormula.c | 474 -- src/base/ver/verParse.c | 117 - src/base/ver/verStream.c | 443 -- 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/cuddAPI.c | 2 +- src/bdd/cudd/cuddAddAbs.c | 2 +- src/bdd/cudd/cuddAddApply.c | 2 +- src/bdd/cudd/cuddAddFind.c | 2 +- src/bdd/cudd/cuddAddInv.c | 2 +- src/bdd/cudd/cuddAddIte.c | 2 +- src/bdd/cudd/cuddAddNeg.c | 2 +- src/bdd/cudd/cuddAddWalsh.c | 2 +- src/bdd/cudd/cuddAndAbs.c | 2 +- src/bdd/cudd/cuddAnneal.c | 2 +- src/bdd/cudd/cuddApa.c | 2 +- src/bdd/cudd/cuddApprox.c | 2 +- src/bdd/cudd/cuddBddAbs.c | 2 +- src/bdd/cudd/cuddBddCorr.c | 2 +- src/bdd/cudd/cuddBddIte.c | 2 +- src/bdd/cudd/cuddBridge.c | 2 +- src/bdd/cudd/cuddCache.c | 2 +- src/bdd/cudd/cuddCheck.c | 2 +- src/bdd/cudd/cuddClip.c | 2 +- src/bdd/cudd/cuddCof.c | 2 +- src/bdd/cudd/cuddCompose.c | 2 +- src/bdd/cudd/cuddDecomp.c | 2 +- src/bdd/cudd/cuddEssent.c | 2 +- src/bdd/cudd/cuddExact.c | 2 +- src/bdd/cudd/cuddExport.c | 2 +- src/bdd/cudd/cuddGenCof.c | 2 +- src/bdd/cudd/cuddGenetic.c | 2 +- src/bdd/cudd/cuddGroup.c | 2 +- src/bdd/cudd/cuddHarwell.c | 2 +- src/bdd/cudd/cuddInit.c | 2 +- src/bdd/cudd/cuddInteract.c | 2 +- src/bdd/cudd/cuddLCache.c | 2 +- src/bdd/cudd/cuddLevelQ.c | 2 +- src/bdd/cudd/cuddLinear.c | 2 +- src/bdd/cudd/cuddLiteral.c | 2 +- src/bdd/cudd/cuddMatMult.c | 2 +- src/bdd/cudd/cuddPriority.c | 2 +- src/bdd/cudd/cuddRead.c | 2 +- src/bdd/cudd/cuddRef.c | 2 +- src/bdd/cudd/cuddReorder.c | 2 +- src/bdd/cudd/cuddSat.c | 2 +- src/bdd/cudd/cuddSign.c | 2 +- src/bdd/cudd/cuddSolve.c | 2 +- src/bdd/cudd/cuddSplit.c | 2 +- src/bdd/cudd/cuddSubsetHB.c | 2 +- src/bdd/cudd/cuddSubsetSP.c | 2 +- src/bdd/cudd/cuddSymmetry.c | 2 +- src/bdd/cudd/cuddTable.c | 2 +- src/bdd/cudd/cuddUtil.c | 2 +- src/bdd/cudd/cuddWindow.c | 2 +- src/bdd/cudd/cuddZddCount.c | 2 +- src/bdd/cudd/cuddZddFuncs.c | 2 +- src/bdd/cudd/cuddZddGroup.c | 2 +- src/bdd/cudd/cuddZddIsop.c | 2 +- src/bdd/cudd/cuddZddLin.c | 2 +- src/bdd/cudd/cuddZddMisc.c | 2 +- src/bdd/cudd/cuddZddPort.c | 2 +- src/bdd/cudd/cuddZddReord.c | 2 +- src/bdd/cudd/cuddZddSetop.c | 2 +- src/bdd/cudd/cuddZddSymm.c | 2 +- src/bdd/cudd/cuddZddUtil.c | 2 +- src/bdd/cudd/testcudd.c | 2 +- src/bdd/dsd/dsd.h | 29 +- src/bdd/dsd/dsdApi.c | 3 +- src/bdd/dsd/dsdCheck.c | 4 +- src/bdd/dsd/dsdInt.h | 9 +- src/bdd/dsd/dsdMan.c | 1 - src/bdd/dsd/dsdProc.c | 4 +- src/bdd/dsd/dsdTree.c | 304 +- src/bdd/epd/epd.c | 2 +- src/bdd/mtr/mtrBasic.c | 2 +- src/bdd/mtr/mtrGroup.c | 2 +- src/bdd/parse/module.make | 1 - src/bdd/parse/parse.h | 7 +- src/bdd/parse/parseCore.c | 2 +- src/bdd/parse/parseEqn.c | 349 - src/bdd/parse/parseInt.h | 11 +- src/bdd/parse/parseStack.c | 10 +- src/bdd/reo/module.make | 1 - src/bdd/reo/reo.h | 24 +- src/bdd/reo/reoProfile.c | 2 +- src/bdd/reo/reoShuffle.c | 224 - src/bdd/reo/reoSwap.c | 26 +- src/bdd/reo/reoTransfer.c | 14 +- src/generic.c | 2 +- src/generic.h | 14 +- src/map/fpga/fpga.c | 72 +- src/map/fpga/fpga.h | 41 +- src/map/fpga/fpgaCore.c | 49 +- src/map/fpga/fpgaCreate.c | 13 +- src/map/fpga/fpgaCut.c | 54 +- src/map/fpga/fpgaCutUtils.c | 10 +- src/map/fpga/fpgaFanout.c | 2 +- src/map/fpga/fpgaGENERIC.c | 2 +- src/map/fpga/fpgaInt.h | 42 +- src/map/fpga/fpgaLib.c | 91 +- src/map/fpga/fpgaMatch.c | 40 +- src/map/fpga/fpgaSwitch.c | 6 +- src/map/fpga/fpgaTime.c | 69 +- src/map/fpga/fpgaTruth.c | 61 +- src/map/fpga/fpgaUtils.c | 53 +- src/map/fpga/fpgaVec.c | 2 +- src/map/if/if.h | 410 -- src/map/if/ifCore.c | 148 - src/map/if/ifCut.c | 988 --- src/map/if/ifMan.c | 577 -- src/map/if/ifMap.c | 350 - src/map/if/ifReduce.c | 575 -- src/map/if/ifSeq.c | 405 -- src/map/if/ifTime.c | 228 - src/map/if/ifTruth.c | 404 -- src/map/if/ifUtil.c | 658 -- src/map/if/if_.c | 47 - src/map/if/module.make | 8 - src/map/mapper/mapper.c | 22 +- src/map/mapper/mapper.h | 23 +- src/map/mapper/mapperCanon.c | 8 +- src/map/mapper/mapperCore.c | 8 +- src/map/mapper/mapperCreate.c | 12 +- src/map/mapper/mapperCut.c | 9 +- src/map/mapper/mapperCutUtils.c | 2 +- src/map/mapper/mapperFanout.c | 2 +- src/map/mapper/mapperGENERIC.c | 2 +- src/map/mapper/mapperInt.h | 16 +- src/map/mapper/mapperLib.c | 10 +- src/map/mapper/mapperMatch.c | 2 +- src/map/mapper/mapperRefs.c | 6 +- src/map/mapper/mapperSuper.c | 2 +- src/map/mapper/mapperSwitch.c | 2 +- src/map/mapper/mapperTable.c | 6 +- src/map/mapper/mapperTime.c | 2 +- src/map/mapper/mapperTree.c | 13 +- src/map/mapper/mapperTruth.c | 13 +- src/map/mapper/mapperUtils.c | 2 +- src/map/mapper/mapperVec.c | 2 +- src/map/mio/mio.c | 28 +- src/map/mio/mio.h | 23 +- src/map/mio/mioApi.c | 32 +- src/map/mio/mioFunc.c | 6 +- src/map/mio/mioGENERIC.c | 2 +- src/map/mio/mioInt.h | 9 +- src/map/mio/mioRead.c | 39 +- src/map/mio/mioUtils.c | 10 +- src/map/pcm/module.make | 0 src/map/ply/module.make | 0 src/map/super/super.c | 50 +- src/map/super/super.h | 15 +- src/map/super/superAnd.c | 12 +- src/map/super/superGENERIC.c | 2 +- src/map/super/superGate.c | 4 +- src/map/super/superInt.h | 8 +- src/map/super/superWrite.c | 2 +- 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 | 364 +- src/misc/extra/extraBddAuto.c | 1558 ---- src/misc/extra/extraBddCas.c | 1230 ---- src/misc/extra/extraBddKmap.c | 783 -- src/misc/extra/extraBddMisc.c | 574 +- src/misc/extra/extraBddSymm.c | 2 +- src/misc/extra/extraBddUnate.c | 641 -- src/misc/extra/extraUtilBitMatrix.c | 2 +- src/misc/extra/extraUtilCanon.c | 24 +- src/misc/extra/extraUtilFile.c | 114 +- src/misc/extra/extraUtilMemory.c | 103 +- src/misc/extra/extraUtilMisc.c | 805 +-- src/misc/extra/extraUtilProgress.c | 30 +- src/misc/extra/extraUtilReader.c | 21 +- src/misc/extra/extraUtilTruth.c | 1148 --- src/misc/extra/extraUtilUtil.c | 356 - src/misc/extra/module.make | 10 +- 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/hop/hop.h | 345 + src/misc/hop/hopBalance.c | 391 + src/misc/hop/hopCheck.c | 110 + src/misc/hop/hopDfs.c | 399 ++ src/misc/hop/hopMan.c | 164 + src/misc/hop/hopMem.c | 115 + src/misc/hop/hopObj.c | 271 + src/misc/hop/hopOper.c | 373 + src/misc/hop/hopTable.c | 262 + src/misc/hop/hopUtil.c | 576 ++ src/misc/hop/hop_.c | 48 + src/misc/hop/module.make | 9 + src/misc/mvc/mvc.c | 2 +- src/misc/mvc/mvc.h | 13 +- src/misc/mvc/mvcApi.c | 2 +- src/misc/mvc/mvcCompare.c | 2 +- src/misc/mvc/mvcContain.c | 2 +- src/misc/mvc/mvcCover.c | 2 +- src/misc/mvc/mvcCube.c | 2 +- src/misc/mvc/mvcDivide.c | 2 +- src/misc/mvc/mvcDivisor.c | 2 +- src/misc/mvc/mvcList.c | 2 +- src/misc/mvc/mvcLits.c | 2 +- src/misc/mvc/mvcMan.c | 10 +- src/misc/mvc/mvcOpAlg.c | 2 +- src/misc/mvc/mvcOpBool.c | 2 +- src/misc/mvc/mvcPrint.c | 2 +- src/misc/mvc/mvcSort.c | 2 +- src/misc/mvc/mvcUtils.c | 2 +- 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/st.c | 115 +- src/misc/st/st.h | 52 +- src/misc/st/stmm.c | 105 +- src/misc/st/stmm.h | 10 +- src/misc/util/cpu_stats.c | 122 + src/misc/util/cpu_time.c | 128 + src/misc/util/datalimit.c | 95 + src/misc/util/getopt.c | 84 + src/misc/util/leaks.h | 8 +- src/misc/util/module.make | 9 +- src/misc/util/pathsearch.c | 131 + src/misc/util/safe_mem.c | 104 + src/misc/util/strsav.c | 157 + src/misc/util/texpand.c | 66 + src/misc/util/util.h | 331 + src/misc/util/util_hack.h | 95 - src/misc/vec/vec.h | 80 +- src/misc/vec/vecAtt.h | 391 - src/misc/vec/vecFan.h | 374 + src/misc/vec/vecFlt.h | 630 -- src/misc/vec/vecInt.h | 223 +- src/misc/vec/vecPtr.h | 290 +- src/misc/vec/vecStr.h | 88 +- src/misc/vec/vecVec.h | 114 +- src/opt/cut/abcCut.c | 492 -- src/opt/cut/cut.h | 124 +- src/opt/cut/cutApi.c | 197 - src/opt/cut/cutCut.c | 359 - src/opt/cut/cutExpand.c | 184 - src/opt/cut/cutInt.h | 79 +- src/opt/cut/cutList.h | 120 +- src/opt/cut/cutMan.c | 243 +- src/opt/cut/cutMerge.c | 11 +- src/opt/cut/cutNode.c | 1072 +-- src/opt/cut/cutOracle.c | 428 -- src/opt/cut/cutPre22.c | 988 --- src/opt/cut/cutSeq.c | 184 +- src/opt/cut/cutTable.c | 253 + src/opt/cut/cutTruth.c | 314 +- src/opt/cut/module.make | 7 +- src/opt/dec/dec.h | 118 +- src/opt/dec/decAbc.c | 154 +- src/opt/dec/decFactor.c | 18 +- src/opt/dec/decMan.c | 2 +- src/opt/dec/decPrint.c | 67 +- src/opt/dec/decUtil.c | 2 +- src/opt/fret/fretFlow.c | 696 -- src/opt/fret/fretInit.c | 762 -- src/opt/fret/fretMain.c | 1059 --- src/opt/fret/fretTime.c | 763 -- src/opt/fret/fretime.h | 165 - src/opt/fret/module.make | 5 - src/opt/fxu/fxu.c | 19 +- src/opt/fxu/fxu.h | 21 +- src/opt/fxu/fxuCreate.c | 46 +- src/opt/fxu/fxuHeapD.c | 2 +- src/opt/fxu/fxuHeapS.c | 2 +- src/opt/fxu/fxuInt.h | 12 +- src/opt/fxu/fxuList.c | 2 +- src/opt/fxu/fxuMatrix.c | 4 +- src/opt/fxu/fxuPair.c | 2 +- src/opt/fxu/fxuPrint.c | 2 +- src/opt/fxu/fxuReduce.c | 12 +- src/opt/fxu/fxuSelect.c | 2 +- src/opt/fxu/fxuSingle.c | 140 +- src/opt/fxu/fxuUpdate.c | 5 +- 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 | 419 -- 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/rwr.h | 40 +- src/opt/rwr/rwrDec.c | 7 +- src/opt/rwr/rwrEva.c | 431 +- src/opt/rwr/rwrExp.c | 2 +- src/opt/rwr/rwrLib.c | 2 +- src/opt/rwr/rwrMan.c | 79 +- src/opt/rwr/rwrPrint.c | 33 +- src/opt/rwr/rwrTemp.c | 121 - src/opt/rwr/rwrUtil.c | 2 +- src/opt/sim/module.make | 1 - src/opt/sim/sim.h | 38 +- src/opt/sim/simMan.c | 43 +- src/opt/sim/simSat.c | 2 +- src/opt/sim/simSeq.c | 171 - src/opt/sim/simSupp.c | 17 +- src/opt/sim/simSwitch.c | 6 +- src/opt/sim/simSym.c | 5 +- src/opt/sim/simSymSat.c | 8 +- src/opt/sim/simSymSim.c | 12 +- src/opt/sim/simSymStr.c | 12 +- src/opt/sim/simUtils.c | 210 +- 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/asat/added.c | 126 + src/sat/asat/main.c | 195 + src/sat/asat/module.make | 2 + src/sat/asat/solver.c | 1167 +++ src/sat/asat/solver.h | 137 + src/sat/asat/solver_vec.h | 53 + src/sat/bsat/module.make | 7 - src/sat/bsat/satInter.c | 991 --- src/sat/bsat/satInterA.c | 970 --- src/sat/bsat/satMem.c | 527 -- src/sat/bsat/satMem.h | 80 - src/sat/bsat/satSolver.c | 1358 ---- src/sat/bsat/satSolver.h | 210 - src/sat/bsat/satStore.c | 437 -- src/sat/bsat/satStore.h | 146 - src/sat/bsat/satTrace.c | 109 - src/sat/bsat/satUtil.c | 234 - src/sat/bsat/satVec.h | 83 - src/sat/csat/csat_apis.c | 386 +- src/sat/csat/csat_apis.h | 154 +- src/sat/fraig/fraig.h | 82 +- src/sat/fraig/fraigApi.c | 8 +- src/sat/fraig/fraigCanon.c | 12 +- src/sat/fraig/fraigChoice.c | 241 - src/sat/fraig/fraigFanout.c | 2 +- src/sat/fraig/fraigFeed.c | 6 +- src/sat/fraig/fraigInt.h | 24 +- src/sat/fraig/fraigMan.c | 310 +- src/sat/fraig/fraigMem.c | 4 +- src/sat/fraig/fraigNode.c | 3 +- src/sat/fraig/fraigPrime.c | 8 +- src/sat/fraig/fraigSat.c | 461 +- src/sat/fraig/fraigTable.c | 2 +- src/sat/fraig/fraigUtil.c | 2 +- src/sat/fraig/fraigVec.c | 2 +- src/sat/msat/msat.h | 20 +- src/sat/msat/msatActivity.c | 6 +- src/sat/msat/msatClause.c | 7 +- src/sat/msat/msatClauseVec.c | 2 +- src/sat/msat/msatInt.h | 10 +- src/sat/msat/msatMem.c | 4 +- src/sat/msat/msatOrderH.c | 2 +- src/sat/msat/msatOrderJ.c | 46 +- src/sat/msat/msatQueue.c | 2 +- src/sat/msat/msatRead.c | 2 +- src/sat/msat/msatSolverApi.c | 50 +- src/sat/msat/msatSolverCore.c | 33 +- src/sat/msat/msatSolverIo.c | 2 +- src/sat/msat/msatSolverSearch.c | 10 +- src/sat/msat/msatSort.c | 2 +- src/sat/msat/msatVec.c | 2 +- src/sat/proof/pr.c | 1263 ---- src/sat/proof/pr.h | 65 - src/sat/proof/stats.txt | 66 - todo.txt | 26 - 921 files changed, 81711 insertions(+), 219836 deletions(-) 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 create mode 100644 graph_lib.txt delete mode 100644 readme create mode 100644 src/abc8/aig/aig.h create mode 100644 src/abc8/aig/aigCheck.c create mode 100644 src/abc8/aig/aigCuts.c create mode 100644 src/abc8/aig/aigDfs.c create mode 100644 src/abc8/aig/aigFanout.c create mode 100644 src/abc8/aig/aigFrames.c create mode 100644 src/abc8/aig/aigHaig.c create mode 100644 src/abc8/aig/aigInter.c create mode 100644 src/abc8/aig/aigMan.c create mode 100644 src/abc8/aig/aigMem.c create mode 100644 src/abc8/aig/aigMffc.c create mode 100644 src/abc8/aig/aigObj.c create mode 100644 src/abc8/aig/aigOper.c create mode 100644 src/abc8/aig/aigOrder.c create mode 100644 src/abc8/aig/aigPart.c create mode 100644 src/abc8/aig/aigRepr.c create mode 100644 src/abc8/aig/aigRet.c create mode 100644 src/abc8/aig/aigRetF.c create mode 100644 src/abc8/aig/aigScl.c create mode 100644 src/abc8/aig/aigSeq.c create mode 100644 src/abc8/aig/aigShow.c create mode 100644 src/abc8/aig/aigTable.c create mode 100644 src/abc8/aig/aigTiming.c create mode 100644 src/abc8/aig/aigTruth.c create mode 100644 src/abc8/aig/aigTsim.c create mode 100644 src/abc8/aig/aigUtil.c create mode 100644 src/abc8/aig/aigWin.c create mode 100644 src/abc8/aig/aig_.c create mode 100644 src/abc8/aig/module.make create mode 100644 src/abc8/bsat/module.make create mode 100644 src/abc8/bsat/satInter.c create mode 100644 src/abc8/bsat/satInterA.c create mode 100644 src/abc8/bsat/satMem.c create mode 100644 src/abc8/bsat/satMem.h create mode 100644 src/abc8/bsat/satSolver.c create mode 100644 src/abc8/bsat/satSolver.h create mode 100644 src/abc8/bsat/satStore.c create mode 100644 src/abc8/bsat/satStore.h create mode 100644 src/abc8/bsat/satTrace.c create mode 100644 src/abc8/bsat/satUtil.c create mode 100644 src/abc8/bsat/satVec.h create mode 100644 src/abc8/cnf/cnf.h create mode 100644 src/abc8/cnf/cnfCore.c create mode 100644 src/abc8/cnf/cnfCut.c create mode 100644 src/abc8/cnf/cnfData.c create mode 100644 src/abc8/cnf/cnfMan.c create mode 100644 src/abc8/cnf/cnfMap.c create mode 100644 src/abc8/cnf/cnfPost.c create mode 100644 src/abc8/cnf/cnfUtil.c create mode 100644 src/abc8/cnf/cnfWrite.c create mode 100644 src/abc8/cnf/cnf_.c create mode 100644 src/abc8/cnf/module.make create mode 100644 src/abc8/dar/dar.h create mode 100644 src/abc8/dar/darBalance.c create mode 100644 src/abc8/dar/darCore.c create mode 100644 src/abc8/dar/darCut.c create mode 100644 src/abc8/dar/darData.c create mode 100644 src/abc8/dar/darInt.h create mode 100644 src/abc8/dar/darLib.c create mode 100644 src/abc8/dar/darMan.c create mode 100644 src/abc8/dar/darPrec.c create mode 100644 src/abc8/dar/darRefact.c create mode 100644 src/abc8/dar/darResub.c create mode 100644 src/abc8/dar/darScript.c create mode 100644 src/abc8/dar/dar_.c create mode 100644 src/abc8/dar/module.make create mode 100644 src/abc8/fra/fra.h create mode 100644 src/abc8/fra/fraBmc.c create mode 100644 src/abc8/fra/fraCec.c create mode 100644 src/abc8/fra/fraClass.c create mode 100644 src/abc8/fra/fraClau.c create mode 100644 src/abc8/fra/fraClaus.c create mode 100644 src/abc8/fra/fraCnf.c create mode 100644 src/abc8/fra/fraCore.c create mode 100644 src/abc8/fra/fraImp.c create mode 100644 src/abc8/fra/fraInd.c create mode 100644 src/abc8/fra/fraLcr.c create mode 100644 src/abc8/fra/fraMan.c create mode 100644 src/abc8/fra/fraPart.c create mode 100644 src/abc8/fra/fraSat.c create mode 100644 src/abc8/fra/fraSec.c create mode 100644 src/abc8/fra/fraSim.c create mode 100644 src/abc8/fra/fra_.c create mode 100644 src/abc8/fra/module.make create mode 100644 src/abc8/ioa/ioa.h create mode 100644 src/abc8/ioa/ioaReadAig.c create mode 100644 src/abc8/ioa/ioaUtil.c create mode 100644 src/abc8/ioa/ioaWriteAig.c create mode 100644 src/abc8/ioa/module.make create mode 100644 src/abc8/kit/cloud.c create mode 100644 src/abc8/kit/cloud.h create mode 100644 src/abc8/kit/kit.h create mode 100644 src/abc8/kit/kitAig.c create mode 100644 src/abc8/kit/kitBdd.c create mode 100644 src/abc8/kit/kitCloud.c create mode 100644 src/abc8/kit/kitDsd.c create mode 100644 src/abc8/kit/kitFactor.c create mode 100644 src/abc8/kit/kitGraph.c create mode 100644 src/abc8/kit/kitHop.c create mode 100644 src/abc8/kit/kitIsop.c create mode 100644 src/abc8/kit/kitSop.c create mode 100644 src/abc8/kit/kitTruth.c create mode 100644 src/abc8/kit/kit_.c create mode 100644 src/abc8/kit/module.make create mode 100644 src/abc8/vec2/module.make create mode 100644 src/abc8/vec2/vec2.h create mode 100644 src/abc8/vec2/vecAtt.h create mode 100644 src/abc8/vec2/vecFlt.h create mode 100644 src/abc8/vec2/vecInt.h create mode 100644 src/abc8/vec2/vecPtr.h create mode 100644 src/abc8/vec2/vecStr.h create mode 100644 src/abc8/vec2/vecVec.h delete mode 100644 src/aig/aig/aig.h delete mode 100644 src/aig/aig/aigCheck.c delete mode 100644 src/aig/aig/aigCuts.c delete mode 100644 src/aig/aig/aigDfs.c delete mode 100644 src/aig/aig/aigFanout.c delete mode 100644 src/aig/aig/aigFrames.c delete mode 100644 src/aig/aig/aigHaig.c delete mode 100644 src/aig/aig/aigInter.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/aigRetF.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/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/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/fraClau.c delete mode 100644 src/aig/fra/fraClaus.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/ntl/module.make delete mode 100644 src/aig/ntl/ntl.h delete mode 100644 src/aig/ntl/ntlAig.c delete mode 100644 src/aig/ntl/ntlCheck.c delete mode 100644 src/aig/ntl/ntlDfs.c delete mode 100644 src/aig/ntl/ntlMan.c delete mode 100644 src/aig/ntl/ntlMap.c delete mode 100644 src/aig/ntl/ntlObj.c delete mode 100644 src/aig/ntl/ntlReadBlif.c delete mode 100644 src/aig/ntl/ntlTable.c delete mode 100644 src/aig/ntl/ntlTime.c delete mode 100644 src/aig/ntl/ntlWriteBlif.c delete mode 100644 src/aig/ntl/ntl_.c 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/aig/tim/module.make delete mode 100644 src/aig/tim/tim.c delete mode 100644 src/aig/tim/tim.h delete mode 100644 src/base/abc/1.txt delete mode 100644 src/base/abc/abcBlifMv.c delete mode 100644 src/base/abc/abcHie.c delete mode 100644 src/base/abc/abcLib.c delete mode 100644 src/base/abci/abcAuto.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 create mode 100644 src/base/abci/abcCollapse.c delete mode 100644 src/base/abci/abcDebug.c delete mode 100644 src/base/abci/abcDress.c delete mode 100644 src/base/abci/abcEspresso.c delete mode 100644 src/base/abci/abcExtract.c delete mode 100644 src/base/abci/abcFpgaFast.c delete mode 100644 src/base/abci/abcGen.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/abcMeasure.c delete mode 100644 src/base/abci/abcMini.c delete mode 100644 src/base/abci/abcMulti.c delete mode 100644 src/base/abci/abcMv.c delete mode 100644 src/base/abci/abcOdc.c delete mode 100644 src/base/abci/abcOrder.c delete mode 100644 src/base/abci/abcPlace.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/abcReorder.c delete mode 100644 src/base/abci/abcRestruct.c delete mode 100644 src/base/abci/abcResub.c delete mode 100644 src/base/abci/abcRr.c delete mode 100644 src/base/abci/abcUnate.c delete mode 100644 src/base/abci/abcXsim.c delete mode 100644 src/base/abci/abc_new.h create mode 100644 src/base/abcs/abcRetime.c create mode 100644 src/base/abcs/abcSeq.c create mode 100644 src/base/abcs/abc_.c create mode 100644 src/base/abcs/module.make create mode 100644 src/base/io/ioRead.c delete mode 100644 src/base/io/ioReadAiger.c delete mode 100644 src/base/io/ioReadBaf.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/ioWriteAiger.c delete mode 100644 src/base/io/ioWriteBaf.c delete mode 100644 src/base/io/ioWriteBlifMv.c delete mode 100644 src/base/io/ioWriteList.c delete mode 100644 src/base/io/ioWriteVerilog.c delete mode 100644 src/base/io/io_.c delete mode 100644 src/base/main/libSupport.c 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/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/parse/parseEqn.c delete mode 100644 src/bdd/reo/reoShuffle.c 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/pcm/module.make delete mode 100644 src/map/ply/module.make 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/extraBddAuto.c delete mode 100644 src/misc/extra/extraBddCas.c delete mode 100644 src/misc/extra/extraBddKmap.c delete mode 100644 src/misc/extra/extraBddUnate.c delete mode 100644 src/misc/extra/extraUtilTruth.c delete mode 100644 src/misc/extra/extraUtilUtil.c 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 create mode 100644 src/misc/hop/hop.h create mode 100644 src/misc/hop/hopBalance.c create mode 100644 src/misc/hop/hopCheck.c create mode 100644 src/misc/hop/hopDfs.c create mode 100644 src/misc/hop/hopMan.c create mode 100644 src/misc/hop/hopMem.c create mode 100644 src/misc/hop/hopObj.c create mode 100644 src/misc/hop/hopOper.c create mode 100644 src/misc/hop/hopTable.c create mode 100644 src/misc/hop/hopUtil.c create mode 100644 src/misc/hop/hop_.c create mode 100644 src/misc/hop/module.make 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 create mode 100644 src/misc/util/cpu_stats.c create mode 100644 src/misc/util/cpu_time.c create mode 100644 src/misc/util/datalimit.c create mode 100644 src/misc/util/getopt.c create mode 100644 src/misc/util/pathsearch.c create mode 100644 src/misc/util/safe_mem.c create mode 100644 src/misc/util/strsav.c create mode 100644 src/misc/util/texpand.c create mode 100644 src/misc/util/util.h delete mode 100644 src/misc/util/util_hack.h delete mode 100644 src/misc/vec/vecAtt.h create mode 100644 src/misc/vec/vecFan.h delete mode 100644 src/misc/vec/vecFlt.h delete mode 100644 src/opt/cut/abcCut.c 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/cutOracle.c delete mode 100644 src/opt/cut/cutPre22.c create mode 100644 src/opt/cut/cutTable.c delete mode 100644 src/opt/fret/fretFlow.c delete mode 100644 src/opt/fret/fretInit.c delete mode 100644 src/opt/fret/fretMain.c delete mode 100644 src/opt/fret/fretTime.c delete mode 100644 src/opt/fret/fretime.h delete mode 100644 src/opt/fret/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/rwrTemp.c delete mode 100644 src/opt/sim/simSeq.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 create mode 100644 src/sat/asat/added.c create mode 100644 src/sat/asat/main.c create mode 100644 src/sat/asat/module.make create mode 100644 src/sat/asat/solver.c create mode 100644 src/sat/asat/solver.h create mode 100644 src/sat/asat/solver_vec.h delete mode 100644 src/sat/bsat/module.make delete mode 100644 src/sat/bsat/satInter.c delete mode 100644 src/sat/bsat/satInterA.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/fraig/fraigChoice.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 index 32d8edf7..adb4cf94 100644 --- a/Makefile +++ b/Makefile @@ -6,20 +6,12 @@ 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/opt/fret \ - 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 src/aig/ntl src/aig/tim +MODULES := src/base/abc src/base/abci src/base/abcs src/base/cmd src/base/io src/base/main \ + src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/parse src/bdd/reo \ + src/map/fpga src/map/mapper src/map/mio src/map/super \ + src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/vec \ + src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr src/opt/sim \ + src/sat/asat src/sat/csat src/sat/msat src/sat/fraig default: $(PROG) @@ -29,7 +21,7 @@ OPTFLAGS := -DNDEBUG -O3 CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES)) CXXFLAGS += $(CFLAGS) -LIBS := -ldl -rdynamic -lreadline -ltermcap +LIBS := SRC := GARBAGE := core core.* *.stackdump ./tags $(PROG) @@ -67,10 +59,6 @@ tags: $(PROG): $(OBJ) $(LD) -o $@ $^ $(LIBS) -lib$(PROG).a: $(OBJ) - ar rv $@ $? - ranlib $@ - docs: doxygen doxygen.conf diff --git a/abc.dsp b/abc.dsp index c44a610e..e5f2bd63 100644 --- a/abc.dsp +++ b/abc.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # 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" /I "src/aig/ntl" /I "src/aig/tim" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /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\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\rwr" /I "src\map\fpga" /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\vec" /I "src\misc\hop" /I "src\abc8\aig" /I "src\abc8\bsat" /I "src\abc8\cnf" /I "src\abc8\dar" /I "src\abc8\fra" /I "src\abc8\vec2" /I "src\abc8\ioa" /I "src\abc8\kit" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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 @@ -50,7 +50,7 @@ BSC32=bscmake.exe # 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" +# 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 /machine:I386 /out:"_TEST/abc.exe" !ELSEIF "$(CFG)" == "abc - Win32 Debug" @@ -66,7 +66,7 @@ LINK32=link.exe # 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" /I "src/aig/ntl" /I "src/aig/tim" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /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\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\rwr" /I "src\map\fpga" /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\vec" /I "src\misc\hop" /I "src\abc8\aig" /I "src\abc8\bsat" /I "src\abc8\cnf" /I "src\abc8\dar" /I "src\abc8\fra" /I "src\abc8\vec2" /I "src\abc8\ioa" /I "src\abc8\kit" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /GZ /c # SUBTRACT CPP /X # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -102,10 +102,6 @@ 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 @@ -122,10 +118,6 @@ 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 @@ -134,10 +126,6 @@ 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 @@ -186,27 +174,11 @@ 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 +SOURCE=.\src\base\abci\abcCollapse.c # End Source File # Begin Source File @@ -218,34 +190,14 @@ 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 @@ -254,62 +206,22 @@ 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 @@ -318,22 +230,6 @@ 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 @@ -346,26 +242,10 @@ 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 @@ -386,19 +266,23 @@ SOURCE=.\src\base\abci\abcTiming.c # End Source File # Begin Source File -SOURCE=.\src\base\abci\abcUnate.c +SOURCE=.\src\base\abci\abcUnreach.c # End Source File # Begin Source File -SOURCE=.\src\base\abci\abcUnreach.c +SOURCE=.\src\base\abci\abcVerify.c # End Source File +# End Group +# Begin Group "abcs" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\base\abci\abcVerify.c +SOURCE=.\src\base\abcs\abcRetime.c # End Source File # Begin Source File -SOURCE=.\src\base\abci\abcXsim.c +SOURCE=.\src\base\abcs\abcSeq.c # End Source File # End Group # Begin Group "cmd" @@ -454,11 +338,7 @@ 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 +SOURCE=.\src\base\io\ioRead.c # End Source File # Begin Source File @@ -470,18 +350,6 @@ 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 @@ -502,14 +370,6 @@ 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 @@ -518,10 +378,6 @@ 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 @@ -538,26 +394,14 @@ 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 @@ -581,30 +425,6 @@ SOURCE=.\src\base\main\mainInt.h 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" @@ -910,10 +730,6 @@ 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 @@ -978,10 +794,6 @@ SOURCE=.\src\bdd\reo\reoProfile.c # End Source File # Begin Source File -SOURCE=.\src\bdd\reo\reoShuffle.c -# End Source File -# Begin Source File - SOURCE=.\src\bdd\reo\reoSift.c # End Source File # Begin Source File @@ -1001,26 +813,30 @@ SOURCE=.\src\bdd\reo\reoTransfer.c SOURCE=.\src\bdd\reo\reoUnits.c # End Source File # End Group -# Begin Group "cas" +# End Group +# Begin Group "sat" + +# PROP Default_Filter "" +# Begin Group "asat" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\bdd\cas\cas.h +SOURCE=.\src\sat\asat\added.c # End Source File # Begin Source File -SOURCE=.\src\bdd\cas\casCore.c +SOURCE=.\src\sat\asat\solver.c # End Source File # Begin Source File -SOURCE=.\src\bdd\cas\casDec.c +SOURCE=.\src\sat\asat\solver.h # End Source File -# End Group -# End Group -# Begin Group "sat" +# Begin Source File -# PROP Default_Filter "" +SOURCE=.\src\sat\asat\solver_vec.h +# End Source File +# End Group # Begin Group "msat" # PROP Default_Filter "" @@ -1050,7 +866,7 @@ SOURCE=.\src\sat\msat\msatMem.c # End Source File # Begin Source File -SOURCE=.\src\sat\msat\msatOrderH.c +SOURCE=.\src\sat\msat\msatOrderJ.c # End Source File # Begin Source File @@ -1102,10 +918,6 @@ 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 @@ -1161,66 +973,6 @@ SOURCE=.\src\sat\csat\csat_apis.c 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\satInterA.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" @@ -1318,10 +1070,6 @@ 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 @@ -1334,18 +1082,6 @@ 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 @@ -1366,15 +1102,11 @@ 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 +SOURCE=.\src\opt\cut\cutSeq.c # End Source File # Begin Source File -SOURCE=.\src\opt\cut\cutSeq.c +SOURCE=.\src\opt\cut\cutTable.c # End Source File # Begin Source File @@ -1426,10 +1158,6 @@ 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 @@ -1457,1576 +1185,880 @@ SOURCE=.\src\opt\sim\simSymStr.c SOURCE=.\src\opt\sim\simUtils.c # End Source File # End Group -# Begin Group "ret" +# End Group +# Begin Group "map" # PROP Default_Filter "" -# Begin Source File +# Begin Group "fpga" -SOURCE=.\src\opt\ret\retArea.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\opt\ret\retCore.c +SOURCE=.\src\map\fpga\fpga.c # End Source File # Begin Source File -SOURCE=.\src\opt\ret\retDelay.c +SOURCE=.\src\map\fpga\fpga.h # End Source File # Begin Source File -SOURCE=.\src\opt\ret\retFlow.c +SOURCE=.\src\map\fpga\fpgaCore.c # End Source File # Begin Source File -SOURCE=.\src\opt\ret\retIncrem.c +SOURCE=.\src\map\fpga\fpgaCreate.c # End Source File # Begin Source File -SOURCE=.\src\opt\ret\retInit.c +SOURCE=.\src\map\fpga\fpgaCut.c # End Source File # Begin Source File -SOURCE=.\src\opt\ret\retInt.h +SOURCE=.\src\map\fpga\fpgaCutUtils.c # End Source File # Begin Source File -SOURCE=.\src\opt\ret\retLvalue.c +SOURCE=.\src\map\fpga\fpgaFanout.c # End Source File -# End Group -# Begin Group "res" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\opt\res\res.h +SOURCE=.\src\map\fpga\fpgaInt.h # End Source File # Begin Source File -SOURCE=.\src\opt\res\resCore.c +SOURCE=.\src\map\fpga\fpgaLib.c # End Source File # Begin Source File -SOURCE=.\src\opt\res\resDivs.c +SOURCE=.\src\map\fpga\fpgaMatch.c # End Source File # Begin Source File -SOURCE=.\src\opt\res\resFilter.c +SOURCE=.\src\map\fpga\fpgaSwitch.c # End Source File # Begin Source File -SOURCE=.\src\opt\res\resInt.h +SOURCE=.\src\map\fpga\fpgaTime.c # End Source File # Begin Source File -SOURCE=.\src\opt\res\resSat.c +SOURCE=.\src\map\fpga\fpgaTruth.c # End Source File # Begin Source File -SOURCE=.\src\opt\res\resSim.c +SOURCE=.\src\map\fpga\fpgaUtils.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 -# Begin Group "fret" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\fret\fretFlow.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fret\fretime.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fret\fretInit.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fret\fretMain.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fret\fretTime.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\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\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\pcmMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmMap.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 -# Begin Group "ply" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\ply\ply.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyAbc.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyIter.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyNtk.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\ply\plyPar.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 +SOURCE=.\src\map\fpga\fpgaVec.c # End Source File # End Group -# Begin Group "vec" +# Begin Group "mapper" # 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 +SOURCE=.\src\map\mapper\mapper.c # End Source File # Begin Source File -SOURCE=.\src\misc\vec\vecVec.h +SOURCE=.\src\map\mapper\mapper.h # End Source File -# End Group -# Begin Group "espresso" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\espresso\cofactor.c +SOURCE=.\src\map\mapper\mapperCanon.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\cols.c +SOURCE=.\src\map\mapper\mapperCore.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\compl.c +SOURCE=.\src\map\mapper\mapperCreate.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\contain.c +SOURCE=.\src\map\mapper\mapperCut.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\cubehack.c +SOURCE=.\src\map\mapper\mapperCutUtils.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\cubestr.c +SOURCE=.\src\map\mapper\mapperFanout.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\cvrin.c +SOURCE=.\src\map\mapper\mapperInt.h # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\cvrm.c +SOURCE=.\src\map\mapper\mapperLib.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\cvrmisc.c +SOURCE=.\src\map\mapper\mapperMatch.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\cvrout.c +SOURCE=.\src\map\mapper\mapperRefs.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\dominate.c +SOURCE=.\src\map\mapper\mapperSuper.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\equiv.c +SOURCE=.\src\map\mapper\mapperSwitch.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\espresso.c +SOURCE=.\src\map\mapper\mapperTable.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\espresso.h +SOURCE=.\src\map\mapper\mapperTime.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\essen.c +SOURCE=.\src\map\mapper\mapperTree.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\exact.c +SOURCE=.\src\map\mapper\mapperTruth.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\expand.c +SOURCE=.\src\map\mapper\mapperUtils.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\gasp.c +SOURCE=.\src\map\mapper\mapperVec.c # End Source File -# Begin Source File +# End Group +# Begin Group "mio" -SOURCE=.\src\misc\espresso\gimpel.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\espresso\globals.c +SOURCE=.\src\map\mio\mio.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\hack.c +SOURCE=.\src\map\mio\mio.h # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\indep.c +SOURCE=.\src\map\mio\mioApi.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\irred.c +SOURCE=.\src\map\mio\mioFunc.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\map.c +SOURCE=.\src\map\mio\mioInt.h # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\matrix.c +SOURCE=.\src\map\mio\mioRead.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\mincov.c +SOURCE=.\src\map\mio\mioUtils.c # End Source File -# Begin Source File +# End Group +# Begin Group "super" -SOURCE=.\src\misc\espresso\mincov.h -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\espresso\mincov_int.h +SOURCE=.\src\map\super\super.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\opo.c +SOURCE=.\src\map\super\super.h # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\pair.c +SOURCE=.\src\map\super\superAnd.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\part.c +SOURCE=.\src\map\super\superGate.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\primes.c +SOURCE=.\src\map\super\superInt.h # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\reduce.c +SOURCE=.\src\map\super\superWrite.c # End Source File -# Begin Source File +# End Group +# End Group +# Begin Group "misc" -SOURCE=.\src\misc\espresso\rows.c -# End Source File -# Begin Source File +# PROP Default_Filter "" +# Begin Group "extra" -SOURCE=.\src\misc\espresso\set.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\espresso\setc.c +SOURCE=.\src\misc\extra\extra.h # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\sharp.c +SOURCE=.\src\misc\extra\extraBddMisc.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\sminterf.c +SOURCE=.\src\misc\extra\extraBddSymm.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\solution.c +SOURCE=.\src\misc\extra\extraUtilBitMatrix.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\sparse.c +SOURCE=.\src\misc\extra\extraUtilCanon.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\sparse.h +SOURCE=.\src\misc\extra\extraUtilFile.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\sparse_int.h +SOURCE=.\src\misc\extra\extraUtilMemory.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\unate.c +SOURCE=.\src\misc\extra\extraUtilMisc.c # End Source File # Begin Source File -SOURCE=.\src\misc\espresso\verify.c +SOURCE=.\src\misc\extra\extraUtilProgress.c # End Source File -# End Group -# Begin Group "util" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\util\util_hack.h +SOURCE=.\src\misc\extra\extraUtilReader.c # End Source File # End Group -# Begin Group "nm" +# Begin Group "st" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\nm\nm.h +SOURCE=.\src\misc\st\st.c # End Source File # Begin Source File -SOURCE=.\src\misc\nm\nmApi.c +SOURCE=.\src\misc\st\st.h # End Source File # Begin Source File -SOURCE=.\src\misc\nm\nmInt.h +SOURCE=.\src\misc\st\stmm.c # End Source File # Begin Source File -SOURCE=.\src\misc\nm\nmTable.c +SOURCE=.\src\misc\st\stmm.h # End Source File # End Group -# Begin Group "hash" +# Begin Group "util" # 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 +SOURCE=.\src\misc\util\cpu_stats.c # 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 +SOURCE=.\src\misc\util\cpu_time.c # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopBalance.c +SOURCE=.\src\misc\util\datalimit.c # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopCheck.c +SOURCE=.\src\misc\util\getopt.c # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopDfs.c +SOURCE=.\src\misc\util\leaks.h # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopMan.c +SOURCE=.\src\misc\util\pathsearch.c # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopMem.c +SOURCE=.\src\misc\util\safe_mem.c # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopObj.c +SOURCE=.\src\misc\util\stdlib_hack.h # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopOper.c +SOURCE=.\src\misc\util\strsav.c # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopTable.c +SOURCE=.\src\misc\util\texpand.c # End Source File # Begin Source File -SOURCE=.\src\aig\hop\hopUtil.c +SOURCE=.\src\misc\util\util.h # End Source File # End Group -# Begin Group "ivy" +# Begin Group "mvc" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\ivy\ivy.h +SOURCE=.\src\misc\mvc\mvc.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyBalance.c +SOURCE=.\src\misc\mvc\mvc.h # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyCanon.c +SOURCE=.\src\misc\mvc\mvcApi.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyCheck.c +SOURCE=.\src\misc\mvc\mvcCompare.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyCut.c +SOURCE=.\src\misc\mvc\mvcContain.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyCutTrav.c +SOURCE=.\src\misc\mvc\mvcCover.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyDfs.c +SOURCE=.\src\misc\mvc\mvcCube.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyDsd.c +SOURCE=.\src\misc\mvc\mvcDivide.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyFanout.c +SOURCE=.\src\misc\mvc\mvcDivisor.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyFastMap.c +SOURCE=.\src\misc\mvc\mvcList.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyFraig.c +SOURCE=.\src\misc\mvc\mvcLits.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyHaig.c +SOURCE=.\src\misc\mvc\mvcMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyMan.c +SOURCE=.\src\misc\mvc\mvcOpAlg.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyMem.c +SOURCE=.\src\misc\mvc\mvcOpBool.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyMulti.c +SOURCE=.\src\misc\mvc\mvcPrint.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyObj.c +SOURCE=.\src\misc\mvc\mvcSort.c # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyOper.c +SOURCE=.\src\misc\mvc\mvcUtils.c # End Source File +# End Group +# Begin Group "vec" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\ivy\ivyResyn.c +SOURCE=.\src\misc\vec\vec.h # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyRwr.c +SOURCE=.\src\misc\vec\vecFan.h # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivySeq.c +SOURCE=.\src\misc\vec\vecInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyShow.c +SOURCE=.\src\misc\vec\vecPtr.h # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyTable.c +SOURCE=.\src\misc\vec\vecStr.h # End Source File # Begin Source File -SOURCE=.\src\aig\ivy\ivyUtil.c +SOURCE=.\src\misc\vec\vecVec.h # End Source File # End Group -# Begin Group "rwt" +# Begin Group "hop" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\rwt\rwt.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\rwt\rwtDec.c +SOURCE=.\src\misc\hop\hop.h # End Source File # Begin Source File -SOURCE=.\src\aig\rwt\rwtMan.c +SOURCE=.\src\misc\hop\hopBalance.c # End Source File # Begin Source File -SOURCE=.\src\aig\rwt\rwtUtil.c +SOURCE=.\src\misc\hop\hopCheck.c # End Source File -# End Group -# Begin Group "deco" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\deco\deco.h +SOURCE=.\src\misc\hop\hopDfs.c # End Source File -# End Group -# Begin Group "mem" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\mem\mem.c +SOURCE=.\src\misc\hop\hopMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\mem\mem.h +SOURCE=.\src\misc\hop\hopMem.c # End Source File -# End Group -# Begin Group "ioa" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\ioa\ioa.h +SOURCE=.\src\misc\hop\hopObj.c # End Source File # Begin Source File -SOURCE=.\src\aig\ioa\ioaReadAig.c +SOURCE=.\src\misc\hop\hopOper.c # End Source File # Begin Source File -SOURCE=.\src\aig\ioa\ioaUtil.c +SOURCE=.\src\misc\hop\hopTable.c # End Source File # Begin Source File -SOURCE=.\src\aig\ioa\ioaWriteAig.c +SOURCE=.\src\misc\hop\hopUtil.c # End Source File # End Group -# Begin Group "dar" +# End Group +# Begin Group "abc8" # 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 +# Begin Group "aig" -SOURCE=.\src\aig\dar\darCut.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\dar\darData.c +SOURCE=.\src\abc8\aig\aig.h # End Source File # Begin Source File -SOURCE=.\src\aig\dar\darInt.h +SOURCE=.\src\abc8\aig\aigCheck.c # End Source File # Begin Source File -SOURCE=.\src\aig\dar\darLib.c +SOURCE=.\src\abc8\aig\aigDfs.c # End Source File # Begin Source File -SOURCE=.\src\aig\dar\darMan.c +SOURCE=.\src\abc8\aig\aigFanout.c # End Source File # Begin Source File -SOURCE=.\src\aig\dar\darPrec.c +SOURCE=.\src\abc8\aig\aigFrames.c # End Source File # Begin Source File -SOURCE=.\src\aig\dar\darRefact.c +SOURCE=.\src\abc8\aig\aigHaig.c # End Source File # Begin Source File -SOURCE=.\src\aig\dar\darResub.c +SOURCE=.\src\abc8\aig\aigMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\dar\darScript.c +SOURCE=.\src\abc8\aig\aigMem.c # End Source File -# End Group -# Begin Group "fra" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\fra\fra.h +SOURCE=.\src\abc8\aig\aigMffc.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraBmc.c +SOURCE=.\src\abc8\aig\aigObj.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraCec.c +SOURCE=.\src\abc8\aig\aigOper.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraClass.c +SOURCE=.\src\abc8\aig\aigOrder.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraClau.c +SOURCE=.\src\abc8\aig\aigPart.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraClaus.c +SOURCE=.\src\abc8\aig\aigRepr.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraCnf.c +SOURCE=.\src\abc8\aig\aigRet.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraCore.c +SOURCE=.\src\abc8\aig\aigRetF.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraImp.c +SOURCE=.\src\abc8\aig\aigScl.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraInd.c +SOURCE=.\src\abc8\aig\aigSeq.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraLcr.c +SOURCE=.\src\abc8\aig\aigTable.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraMan.c +SOURCE=.\src\abc8\aig\aigTiming.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraPart.c +SOURCE=.\src\abc8\aig\aigTruth.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraSat.c +SOURCE=.\src\abc8\aig\aigTsim.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraSec.c +SOURCE=.\src\abc8\aig\aigUtil.c # End Source File # Begin Source File -SOURCE=.\src\aig\fra\fraSim.c +SOURCE=.\src\abc8\aig\aigWin.c # End Source File # End Group -# Begin Group "cnf" +# Begin Group "bsat" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\cnf\cnf.h +SOURCE=.\src\abc8\bsat\satInter.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfCore.c +SOURCE=.\src\abc8\bsat\satMem.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfCut.c +SOURCE=.\src\abc8\bsat\satMem.h # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfData.c +SOURCE=.\src\abc8\bsat\satSolver.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfMan.c +SOURCE=.\src\abc8\bsat\satSolver.h # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfMap.c +SOURCE=.\src\abc8\bsat\satStore.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfPost.c +SOURCE=.\src\abc8\bsat\satStore.h # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfUtil.c +SOURCE=.\src\abc8\bsat\satTrace.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfWrite.c +SOURCE=.\src\abc8\bsat\satUtil.c # End Source File -# End Group -# Begin Group "csw" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\csw\csw.h +SOURCE=.\src\abc8\bsat\satVec.h # End Source File -# Begin Source File +# End Group +# Begin Group "cnf" -SOURCE=.\src\aig\csw\cswCore.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\csw\cswCut.c +SOURCE=.\src\abc8\cnf\cnf.h # End Source File # Begin Source File -SOURCE=.\src\aig\csw\cswInt.h +SOURCE=.\src\abc8\cnf\cnfCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\csw\cswMan.c +SOURCE=.\src\abc8\cnf\cnfCut.c # End Source File # Begin Source File -SOURCE=.\src\aig\csw\cswTable.c +SOURCE=.\src\abc8\cnf\cnfData.c # End Source File -# End Group -# Begin Group "kit" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\kit\cloud.c +SOURCE=.\src\abc8\cnf\cnfMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\cloud.h +SOURCE=.\src\abc8\cnf\cnfMap.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kit.h +SOURCE=.\src\abc8\cnf\cnfPost.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitAig.c +SOURCE=.\src\abc8\cnf\cnfUtil.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitBdd.c +SOURCE=.\src\abc8\cnf\cnfWrite.c # End Source File -# Begin Source File +# End Group +# Begin Group "dar" -SOURCE=.\src\aig\kit\kitCloud.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\kit\kitDsd.c +SOURCE=.\src\abc8\dar\dar.h # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitFactor.c +SOURCE=.\src\abc8\dar\darBalance.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitGraph.c +SOURCE=.\src\abc8\dar\darCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitHop.c +SOURCE=.\src\abc8\dar\darCut.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitIsop.c +SOURCE=.\src\abc8\dar\darData.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitSop.c +SOURCE=.\src\abc8\dar\darInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitTruth.c +SOURCE=.\src\abc8\dar\darLib.c # End Source File -# End Group -# Begin Group "bdc" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\bdc\bdc.h +SOURCE=.\src\abc8\dar\darMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcCore.c +SOURCE=.\src\abc8\dar\darPrec.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcDec.c +SOURCE=.\src\abc8\dar\darRefact.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcInt.h +SOURCE=.\src\abc8\dar\darResub.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcTable.c +SOURCE=.\src\abc8\dar\darScript.c # End Source File # End Group -# Begin Group "aig" +# Begin Group "fra" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\aig\aig.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigCheck.c +SOURCE=.\src\abc8\fra\fra.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigCuts.c +SOURCE=.\src\abc8\fra\fraBmc.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigDfs.c +SOURCE=.\src\abc8\fra\fraCec.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigFanout.c +SOURCE=.\src\abc8\fra\fraClass.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigFrames.c +SOURCE=.\src\abc8\fra\fraClau.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigHaig.c +SOURCE=.\src\abc8\fra\fraCnf.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigInter.c +SOURCE=.\src\abc8\fra\fraCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigMan.c +SOURCE=.\src\abc8\fra\fraImp.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigMem.c +SOURCE=.\src\abc8\fra\fraInd.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigMffc.c +SOURCE=.\src\abc8\fra\fraLcr.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigObj.c +SOURCE=.\src\abc8\fra\fraMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigOper.c +SOURCE=.\src\abc8\fra\fraPart.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigOrder.c +SOURCE=.\src\abc8\fra\fraSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigPart.c +SOURCE=.\src\abc8\fra\fraSec.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigRepr.c +SOURCE=.\src\abc8\fra\fraSim.c # End Source File -# Begin Source File +# End Group +# Begin Group "vec2" -SOURCE=.\src\aig\aig\aigRet.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\aig\aigRetF.c +SOURCE=.\src\abc8\vec2\vec2.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigScl.c +SOURCE=.\src\abc8\vec2\vecAtt.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigSeq.c +SOURCE=.\src\abc8\vec2\vecFlt.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigShow.c +SOURCE=.\src\abc8\vec2\vecInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigTable.c +SOURCE=.\src\abc8\vec2\vecPtr.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigTiming.c +SOURCE=.\src\abc8\vec2\vecStr.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigTruth.c +SOURCE=.\src\abc8\vec2\vecVec.h # End Source File -# Begin Source File +# End Group +# Begin Group "ioa" -SOURCE=.\src\aig\aig\aigTsim.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\aig\aigUtil.c +SOURCE=.\src\abc8\ioa\ioa.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigWin.c +SOURCE=.\src\abc8\ioa\ioaReadAig.c # End Source File -# End Group -# Begin Group "bar" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\bar\bar.c +SOURCE=.\src\abc8\ioa\ioaUtil.c # End Source File # Begin Source File -SOURCE=.\src\aig\bar\bar.h +SOURCE=.\src\abc8\ioa\ioaWriteAig.c # End Source File # End Group -# Begin Group "ntl" +# Begin Group "kit" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\ntl\ntl.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ntl\ntlAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ntl\ntlCheck.c +SOURCE=.\src\abc8\kit\cloud.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlDfs.c +SOURCE=.\src\abc8\kit\cloud.h # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlMan.c +SOURCE=.\src\abc8\kit\kit.h # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlMap.c +SOURCE=.\src\abc8\kit\kitAig.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlObj.c +SOURCE=.\src\abc8\kit\kitCloud.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlReadBlif.c +SOURCE=.\src\abc8\kit\kitFactor.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlTable.c +SOURCE=.\src\abc8\kit\kitGraph.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlTime.c +SOURCE=.\src\abc8\kit\kitHop.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlWriteBlif.c +SOURCE=.\src\abc8\kit\kitIsop.c # End Source File -# End Group -# Begin Group "tim" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\tim\tim.c +SOURCE=.\src\abc8\kit\kitSop.c # End Source File # Begin Source File -SOURCE=.\src\aig\tim\tim.h +SOURCE=.\src\abc8\kit\kitTruth.c # End Source File # End Group # End Group diff --git a/abc.rc b/abc.rc index ce5b1240..6028a522 100644 --- a/abc.rc +++ b/abc.rc @@ -1,10 +1,9 @@ # global parameters -set check # checks intermediate networks +#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 +set savesteps 1 # sets the maximum number of backup networks to save # program names for internal calls set dotwin dot.exe @@ -15,10 +14,6 @@ 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 @@ -27,102 +22,48 @@ 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 mu renode -m 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 dret dretime 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 wb write_blif 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" +alias cnf "st; ren -c; write_cnf" +alias prove "st; ren -c; sat" +alias opt "b; ren; b" +alias share "b; ren; fx; b" +alias sharem "b; ren -m; fx; b" +alias sharedsd "b; ren; dsd -g; sw; fx; b" +alias resyn "b; rw; rwz; b; rwz; b" +alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" +alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore" -# 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 bmc2 "frames -i -F 10; orpos; iprove" - -alias t0 "r test/mc1.blif; st; test" -alias t1 "r s27mc2.blif; st; test" -alias t2 "r i/intel_001.aig; ps; indcut -v" +alias scl scleanup +alias ssw ssweep diff --git a/abclib.dsp b/abclib.dsp deleted file mode 100644 index df244f0f..00000000 --- a/abclib.dsp +++ /dev/null @@ -1,2844 +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/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/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/graph_lib.txt b/graph_lib.txt new file mode 100644 index 00000000..14bfc335 --- /dev/null +++ b/graph_lib.txt @@ -0,0 +1,1407 @@ + +Class 1. Func 0. Functions = 15. Volume = 33. 0000000000000001 + 288 : 0x0001 tt=0000000000000001 lev=2 vol=3 (d'a')(c'b') + 367 : 0x0001 tt=0000000000000001 lev=2 vol=3 (d'b')(c'a') + 457 : 0x0001 tt=0000000000000001 lev=2 vol=3 (d'c')(b'a') + 637 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((b'a')c')d' + 693 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((b'a')d')c' + 768 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((c'a')b')d' + 781 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((c'a')d')b' + 880 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((c'b')a')d' + 914 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((c'b')d')a' + 1103 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'a')b')c' + 1110 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'a')c')b' + 1231 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'b')a')c' + 1236 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'b')c')a' + 1397 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'c')a')b' + 1404 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'c')b')a' + +Class 2. Func 1. Functions = 3. Volume = 6. 0000000000000011 + 190 : 0x0003 tt=0000000000000011 lev=2 vol=2 (c'b')d' + 356 : 0x0003 tt=0000000000000011 lev=2 vol=2 (d'b')c' + 449 : 0x0003 tt=0000000000000011 lev=2 vol=2 (d'c')b' + +Class 3. Func 2. Functions = 3. Volume = 7. 0000000000000110 + 461 : 0x0006 tt=0000000000000110 lev=2 vol=4 (d'c')(b+a) + 716 : 0x0006 tt=0000000000000110 lev=3 vol=4 ((b+a)c')d' + 731 : 0x0006 tt=0000000000000110 lev=3 vol=4 ((b+a)d')c' + +Class 4. Func 3. Functions = 3. Volume = 7. 0000000000000111 + 452 : 0x0007 tt=0000000000000111 lev=2 vol=3 (d'c')(ba)' + 525 : 0x0007 tt=0000000000000111 lev=3 vol=3 ((ba)'c')d' + 552 : 0x0007 tt=0000000000000111 lev=3 vol=3 ((ba)'d')c' + +Class 5. Func 4. Functions = 1. Volume = 1. 0000000000001111 + 33 : 0x000f tt=0000000000001111 lev=1 vol=1 d'c' + +Class 6. Func 5. Functions = 6. Volume = 22. 0000000000010110 + 671 : 0x0016 tt=0000000000010110 lev=3 vol=6 ((b'a')+c)'((ba)'d') + 773 : 0x0016 tt=0000000000010110 lev=3 vol=6 ((c'a')+b)'((ca)'d') + 889 : 0x0016 tt=0000000000010110 lev=3 vol=6 ((c'b')+a)'((cb)'d') + 1538 : 0x0016 tt=0000000000010110 lev=4 vol=6 (((ba)'c')+(b'a'))d' + 1732 : 0x0016 tt=0000000000010110 lev=4 vol=6 (((b'a')+c)'d')(ba)' + 1734 : 0x0016 tt=0000000000010110 lev=4 vol=6 (((b'a')+c)'(ba)')d' + +Class 7. Func 6. Functions = 6. Volume = 22. 0000000000010111 + 635 : 0x0017 tt=0000000000010111 lev=3 vol=5 ((b'a')'c)'((ba)'d') + 767 : 0x0017 tt=0000000000010111 lev=3 vol=5 ((c'a')'b)'((ca)'d') + 879 : 0x0017 tt=0000000000010111 lev=3 vol=5 ((c'b')'a)'((cb)'d') + 1536 : 0x0017 tt=0000000000010111 lev=4 vol=5 (((ba)'c')'(b'a')')'d' + 1671 : 0x0017 tt=0000000000010111 lev=4 vol=5 (((b'a')'c)'d')(ba)' + 1674 : 0x0017 tt=0000000000010111 lev=4 vol=5 (((b'a')'c)'(ba)')d' + +Class 8. Func 7. Functions = 29. Volume = 80. 0000000000011000 + 733 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((b+a)'d')(c+a) + 735 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((b+a)'d')(c+b) + 804 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+a)d')(b+a)' + 806 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+a)d')(c+b) + 811 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+a)(b+a)')d' + 832 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb)'d')((ca')'(ba)')' + 834 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb)'d')((c'a')'(b'a)') + 837 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb)'(b'a)')((c'a')'d') + 843 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb)'(c'a')')((b'a)'d') + 853 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b)'(b'a')')'((c'a')'d') + 856 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b)'(ca')')'((ba')'d') + 866 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb')'(ba)')'((ca)'d') + 874 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb')'(c'a)')'((b'a)'d') + 916 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b')'d')((ca)'(ba')') + 917 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b')'d')((c'a)'(b'a')')' + 941 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b')'(ba')')((ca)'d') + 945 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b')'(ca)')((ba')'d') + 971 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+b)d')(b+a)' + 972 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+b)d')(c+a) + 989 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+b)(b+a)')d' + 1004 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+b)(c+a))d' + 1528 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((ba)'c')'d')((b'a')'c)' + 1618 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a)'d')(c'a')')(cb)' + 1622 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a)'d')(cb)')(c'a')' + 1660 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((ba')'d')(ca)')(c'b')' + 1663 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((ba')'d')(c'b')')(ca)' + 1669 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a')c)'((ba)c')')'d' + 1672 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a')'c)'d')((ba)'c')' + 1676 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a')'c)'((ba)'c')')d' + +Class 9. Func 8. Functions = 9. Volume = 29. 0000000000011001 + 732 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((b+a)'d')(ca)' + 734 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((b+a)'d')(cb)' + 747 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((ca)'d')(b+a)' + 751 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((ca)'(b+a)')d' + 755 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((c'a)'b)'((b'a)'d') + 827 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((cb)'d')(b+a)' + 838 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((cb)'(b+a)')d' + 847 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((c'b)'a)'((ba')'d') + 1511 : 0x0019 tt=0000000000011001 lev=4 vol=5 (((ba)c')'(b'a')')'d' + +Class 10. Func 9. Functions = 4. Volume = 12. 0000000000011011 + 621 : 0x001b tt=0000000000011011 lev=3 vol=4 ((ba')'d')(ca)' + 746 : 0x001b tt=0000000000011011 lev=3 vol=4 ((ca)'d')(ba')' + 749 : 0x001b tt=0000000000011011 lev=3 vol=4 ((ca)'(ba')')d' + 757 : 0x001b tt=0000000000011011 lev=3 vol=4 ((c'a)'(b'a')')'d' + +Class 11. Func 10. Functions = 1. Volume = 3. 0000000000011110 + 667 : 0x001e tt=0000000000011110 lev=3 vol=4 ((b'a')+c)'d' + +Class 12. Func 11. Functions = 1. Volume = 3. 0000000000011111 + 631 : 0x001f tt=0000000000011111 lev=3 vol=3 ((b'a')'c)'d' + +Class 13. Func 12. Functions = 1. Volume = 2. 0000000000111100 + 207 : 0x003c tt=0000000000111100 lev=2 vol=3 (c+b)d' + +Class 14. Func 13. Functions = 9. Volume = 29. 0000000000111101 + 829 : 0x003d tt=0000000000111101 lev=3 vol=5 ((cb)'d')((b'a)c')' + 831 : 0x003d tt=0000000000111101 lev=3 vol=5 ((cb)'d')((c'a)b')' + 878 : 0x003d tt=0000000000111101 lev=3 vol=5 ((c'b')a)'((cb)'d') + 984 : 0x003d tt=0000000000111101 lev=3 vol=5 ((c+b)'(b'a')')'d' + 1001 : 0x003d tt=0000000000111101 lev=3 vol=5 ((c+b)'(c'a')')'d' + 1591 : 0x003d tt=0000000000111101 lev=4 vol=5 (((b'a)c')'d')(cb)' + 1594 : 0x003d tt=0000000000111101 lev=4 vol=5 (((b'a)c')'(cb)')d' + 1600 : 0x003d tt=0000000000111101 lev=4 vol=5 (((b'a)'c')'(cb')')'d' + 1711 : 0x003d tt=0000000000111101 lev=4 vol=5 (((b'a')'c')+b)'d' + +Class 15. Func 14. Functions = 1. Volume = 2. 0000000000111111 + 150 : 0x003f tt=0000000000111111 lev=2 vol=2 (cb)'d' + +Class 16. Func 15. Functions = 3. Volume = 9. 0000000001101001 + 721 : 0x0069 tt=0000000001101001 lev=3 vol=5 ((b+a)+c)'d' + 794 : 0x0069 tt=0000000001101001 lev=3 vol=5 ((c+a)+b)'d' + 958 : 0x0069 tt=0000000001101001 lev=3 vol=5 ((c+b)+a)'d' + +Class 17. Func 16. Functions = 11. Volume = 43. 0000000001101011 + 1086 : 0x006b tt=0000000001101011 lev=3 vol=8 ((d'a)(c'b')')+((c+b)'d') + 1121 : 0x006b tt=0000000001101011 lev=3 vol=7 ((d'a')(c'b')')+((cb)'d') + 1198 : 0x006b tt=0000000001101011 lev=3 vol=7 ((d'b)(c'a)')+((ca')'d') + 1351 : 0x006b tt=0000000001101011 lev=3 vol=7 ((d'c)(b'a)')+((ba')'d') + 1480 : 0x006b tt=0000000001101011 lev=4 vol=7 (((ba)c)'d')((c+b)a')' + 1584 : 0x006b tt=0000000001101011 lev=4 vol=7 (((b'a)'c)d')+((ba')'d') + 1585 : 0x006b tt=0000000001101011 lev=4 vol=7 (((b'a)'c)'d')+((ba')d') + 1586 : 0x006b tt=0000000001101011 lev=4 vol=7 (((b'a)'c)'d')+((d'a')b) + 1587 : 0x006b tt=0000000001101011 lev=4 vol=7 (((b'a)'c)'d')+((d'b)a') + 1589 : 0x006b tt=0000000001101011 lev=4 vol=6 (((b'a)'c)+(ba'))'d' + 1644 : 0x006b tt=0000000001101011 lev=4 vol=6 (((ba')+c)(b'a)')'d' + +Class 18. Func 17. Functions = 1. Volume = 3. 0000000001101111 + 714 : 0x006f tt=0000000001101111 lev=3 vol=4 ((b+a)'c)'d' + +Class 19. Func 18. Functions = 11. Volume = 35. 0000000001111110 + 812 : 0x007e tt=0000000001111110 lev=3 vol=6 ((c+a)'(b+a)')'d' + 990 : 0x007e tt=0000000001111110 lev=3 vol=6 ((c+b)'(b+a)')'d' + 1006 : 0x007e tt=0000000001111110 lev=3 vol=6 ((c+b)'(c+a)')'d' + 1477 : 0x007e tt=0000000001111110 lev=4 vol=6 (((ba)c)'d')((b'a')c')' + 1478 : 0x007e tt=0000000001111110 lev=4 vol=6 (((ba)c)'d')((c'a')b')' + 1479 : 0x007e tt=0000000001111110 lev=4 vol=6 (((ba)c)'d')((c'b')a')' + 1692 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')c')'d')((ba)c)' + 1693 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')c')'d')((ca)b)' + 1694 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')c')'d')((cb)a)' + 1708 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')c')'((ba)c)')d' + 1728 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')'c')'((ba)'c)')'d' + +Class 20. Func 19. Functions = 3. Volume = 9. 0000000001111111 + 494 : 0x007f tt=0000000001111111 lev=3 vol=3 ((ba)c)'d' + 741 : 0x007f tt=0000000001111111 lev=3 vol=3 ((ca)b)'d' + 820 : 0x007f tt=0000000001111111 lev=3 vol=3 ((cb)a)'d' + +Class 21. Func 20. Functions = 6. Volume = 12. 0000000011111111 + 229 : 0x00ff tt=0000000011111111 lev=2 vol=2 (da)'d' + 264 : 0x00ff tt=0000000011111111 lev=2 vol=2 (da')'d' + 316 : 0x00ff tt=0000000011111111 lev=2 vol=2 (db)'d' + 343 : 0x00ff tt=0000000011111111 lev=2 vol=2 (db')'d' + 400 : 0x00ff tt=0000000011111111 lev=2 vol=2 (dc)'d' + 432 : 0x00ff tt=0000000011111111 lev=2 vol=2 (dc')'d' + +Class 22. Func 21. Functions = 18. Volume = 57. 0000000100010110 + 1116 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'a')(cb)')+((da)'(c'b')) + 1122 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'a')+(c'b'))((da)'(cb)') + 1243 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'b')(ca)')+((db)'(c'a')) + 1250 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'b')'(c'a')')'((d'a')+(c'b')) + 1251 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'b')+(c'a'))((d'a')'(c'b')')' + 1252 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'b')+(c'a'))((db)'(ca)') + 1410 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')(ba)')+((dc)'(b'a')) + 1426 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')'(b'a')')'((d'a')+(c'b')) + 1427 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')'(b'a')')'((d'b')+(c'a')) + 1429 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')+(b'a'))((d'a')'(c'b')')' + 1430 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')+(b'a'))((d'b')'(c'a')')' + 1431 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')+(b'a'))((dc)'(ba)') + 1527 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((ba)'c')d')+((dc)'(b'a')) + 1572 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((ba)'d')c')+((dc)'(b'a')) + 1677 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((b'a')'c)'((ba)'d'))+((b'a')c') + 1710 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((b'a')c')+((ba)'d'))((b'a')'c)' + 1757 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((b'a')'d)'((ba)'c'))+((b'a')d') + 1770 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((b'a')d')+((ba)'c'))((b'a')'d)' + +Class 24. Func 22. Functions = 27. Volume = 85. 0000000100011000 + 786 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((c'a')+d)'((ca)'(b+a)') + 841 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((cb)'(b+a)')((c'a')+d)' + 928 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((c'b')+d)'((ca)'(b+a)') + 936 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((c'b')+d)'((cb)'(b+a)') + 1114 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'a')+c)'((da)'(b+a)') + 1168 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((db)'(b+a)')((d'a')+c)' + 1240 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'b')+c)'((da)'(b+a)') + 1241 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'b')+c)'((db)'(b+a)') + 1400 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'c')+a)'((dc)'(b+a)') + 1409 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'c')+b)'((dc)'(b+a)') + 1455 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d+c)'(ba)')'((d'c')'(b'a')')' + 1514 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)c')'(b'a')')'((c'a')+d)' + 1516 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)c')'(b'a')')'((c'b')+d)' + 1520 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)c')'(d+c)')'((d+c)(b'a')')' + 1535 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)'c')+d)'((d'c')'(b'a')')' + 1556 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)d')'(b'a')')'((d'a')+c)' + 1558 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)d')'(b'a')')'((d'b')+c)' + 1568 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)d')'(d+c)')'((d+c)(b'a')')' + 1575 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)'d')+c)'((d'c')'(b'a')')' + 1603 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((b'a)'c')+(d'a'))((d'a)'b)' + 1604 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((b'a)'c')+(d'a'))((d'c')'b)' + 1620 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((b'a)'d')+(c'a'))((c'a)'b)' + 1621 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((b'a)'d')+(c'a'))((d'c')'b)' + 1641 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba')'c')+(d'b'))((d'b)'a)' + 1642 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba')'c')+(d'b'))((d'c')'a)' + 1665 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba')'d')+(c'b'))((c'b)'a)' + 1666 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba')'d')+(c'b'))((d'c')'a)' + +Class 25. Func 23. Functions = 18. Volume = 64. 0000000100011001 + 777 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((c'a')'d)'((ca)'(b+a)') + 840 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((cb)'(b+a)')((c'a')'d)' + 903 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((c'b')'d)'((ca)'(b+a)') + 910 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((c'b')'d)'((cb)'(b+a)') + 1106 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'a')'c)'((da)'(b+a)') + 1167 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((db)'(b+a)')((d'a')'c)' + 1234 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'b')'c)'((da)'(b+a)') + 1235 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'b')'c)'((db)'(b+a)') + 1396 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'c')'a)'((dc)'(b+a)') + 1403 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'c')'b)'((dc)'(b+a)') + 1513 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba)c')'(b'a')')'((c'a')'d)' + 1515 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba)c')'(b'a')')'((c'b')'d)' + 1555 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba)d')'(b'a')')'((d'a')'c)' + 1557 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba)d')'(b'a')')'((d'b')'c)' + 1602 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((b'a)'c')'(d'a')')'((d'a)'b)' + 1619 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((b'a)'d')'(c'a')')'((c'a)'b)' + 1640 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba')'c')'(d'b')')'((d'b)'a)' + 1664 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba')'d')'(c'b')')'((c'b)'a)' + +Class 26. Func 24. Functions = 12. Volume = 40. 0000000100011010 + 785 : 0x011a tt=0000000100011010 lev=3 vol=7 ((c'a')+d)'((ca)'(ba')') + 787 : 0x011a tt=0000000100011010 lev=3 vol=7 ((c'a')+d)'((c'a)'(b'a')')' + 1113 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'a')+c)'((da)'(ba')') + 1115 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'a')+c)'((d'a)'(b'a')')' + 1399 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'c')+a)'((dc)'(ba')') + 1424 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'c')'(b'a')')'((c'a')+d)' + 1425 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'c')'(b'a')')'((d'a')+c)' + 1448 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d+c)'a')'((d'c')'(b'a')')' + 1464 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d+c)'(c'a)')'((d+c)(b'a')')' + 1472 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d+c)'(d'a)')'((d+c)(b'a')')' + 1701 : 0x011a tt=0000000100011010 lev=4 vol=7 (((b'a')c')+d)'((c'a)'(b'a')')' + 1768 : 0x011a tt=0000000100011010 lev=4 vol=7 (((b'a')d')+c)'((d'a)'(b'a')')' + +Class 27. Func 25. Functions = 7. Volume = 29. 0000000100011011 + 776 : 0x011b tt=0000000100011011 lev=3 vol=6 ((c'a')'d)'((ca)'(ba')') + 778 : 0x011b tt=0000000100011011 lev=3 vol=6 ((c'a')'d)'((c'a)'(b'a')')' + 1105 : 0x011b tt=0000000100011011 lev=3 vol=6 ((d'a')'c)'((da)'(ba')') + 1107 : 0x011b tt=0000000100011011 lev=3 vol=6 ((d'a')'c)'((d'a)'(b'a')')' + 1395 : 0x011b tt=0000000100011011 lev=3 vol=6 ((d'c')'a)'((dc)'(ba')') + 1685 : 0x011b tt=0000000100011011 lev=4 vol=6 (((b'a')c')'d)'((c'a)'(b'a')')' + 1764 : 0x011b tt=0000000100011011 lev=4 vol=6 (((b'a')d')'c)'((d'a)'(b'a')')' + +Class 28. Func 26. Functions = 6. Volume = 19. 0000000100011110 + 1315 : 0x011e tt=0000000100011110 lev=3 vol=6 ((dc)'(b'a'))+(d'c') + 1428 : 0x011e tt=0000000100011110 lev=3 vol=6 ((d'c')+(b'a'))(dc)' + 1673 : 0x011e tt=0000000100011110 lev=4 vol=6 (((b'a')'c)'d')+((b'a')c') + 1699 : 0x011e tt=0000000100011110 lev=4 vol=6 (((b'a')c')+d)'((b'a')'c)' + 1743 : 0x011e tt=0000000100011110 lev=4 vol=6 (((b'a')'d)'c')+((b'a')d') + 1767 : 0x011e tt=0000000100011110 lev=4 vol=6 (((b'a')d')+c)'((b'a')'d)' + +Class 29. Func 27. Functions = 4. Volume = 16. 0000000100011111 + 1422 : 0x011f tt=0000000100011111 lev=3 vol=7 ((d'c')(b'a')')+((dc)'(b'a')) + 1423 : 0x011f tt=0000000100011111 lev=3 vol=5 ((d'c')'(b'a')')'(dc)' + 1682 : 0x011f tt=0000000100011111 lev=4 vol=5 (((b'a')c')'d)'((b'a')'c)' + 1763 : 0x011f tt=0000000100011111 lev=4 vol=5 (((b'a')d')'c)'((b'a')'d)' + +Class 30. Func 28. Functions = 5. Volume = 21. 0000000100101100 + 711 : 0x012c tt=0000000100101100 lev=3 vol=7 ((b'a')+d)'((b'a)+c)' + 922 : 0x012c tt=0000000100101100 lev=3 vol=7 ((c'b')+d)'((b'a)+c)' + 1239 : 0x012c tt=0000000100101100 lev=3 vol=7 ((d'b')+c)'((b'a')+d)' + 1407 : 0x012c tt=0000000100101100 lev=3 vol=7 ((d'c')+b)'((da)'(ca')') + 1408 : 0x012c tt=0000000100101100 lev=3 vol=7 ((d'c')+b)'((d'a)'(c'a')')' + +Class 31. Func 29. Functions = 2. Volume = 8. 0000000100101101 + 690 : 0x012d tt=0000000100101101 lev=3 vol=6 ((b'a')'d)'((b'a)+c)' + 898 : 0x012d tt=0000000100101101 lev=3 vol=6 ((c'b')'d)'((b'a)+c)' + +Class 32. Func 30. Functions = 1. Volume = 5. 0000000100101111 + 688 : 0x012f tt=0000000100101111 lev=3 vol=5 ((b'a')'d)'((b'a)'c)' + +Class 33. Func 31. Functions = 10. Volume = 33. 0000000100111100 + 978 : 0x013c tt=0000000100111100 lev=3 vol=7 ((c+b)+d)((b'a')'d)' + 979 : 0x013c tt=0000000100111100 lev=3 vol=7 ((c+b)+d)((c'a')'d)' + 987 : 0x013c tt=0000000100111100 lev=3 vol=7 ((c+b)'(b'a')')'((c+b)+d) + 1003 : 0x013c tt=0000000100111100 lev=3 vol=7 ((c+b)'(c'a')')'((c+b)+d) + 1050 : 0x013c tt=0000000100111100 lev=3 vol=7 ((da)'(cb)')((c'b')+d)' + 1060 : 0x013c tt=0000000100111100 lev=3 vol=7 ((da)'(c'b'))+((cb)'d') + 1101 : 0x013c tt=0000000100111100 lev=3 vol=7 ((da')'(c+b)')'((c'b')'d)' + 1238 : 0x013c tt=0000000100111100 lev=3 vol=6 ((d'b')+c)'((b'a')'d)' + 1406 : 0x013c tt=0000000100111100 lev=3 vol=6 ((d'c')+b)'((c'a')'d)' + 1742 : 0x013c tt=0000000100111100 lev=4 vol=6 (((b'a')'d)'c')+(d'b') + +Class 34. Func 32. Functions = 6. Volume = 18. 0000000100111101 + 973 : 0x013d tt=0000000100111101 lev=3 vol=7 ((c+b)d')+((b'a')c') + 974 : 0x013d tt=0000000100111101 lev=3 vol=7 ((c+b)d')+((c'a')b') + 975 : 0x013d tt=0000000100111101 lev=3 vol=7 ((c+b)d')+((c'b')a') + 985 : 0x013d tt=0000000100111101 lev=3 vol=7 ((c+b)'(b'a')')'((c'b')'d)' + 986 : 0x013d tt=0000000100111101 lev=3 vol=6 ((c+b)'(b'a')')'((c+b)d)' + 1002 : 0x013d tt=0000000100111101 lev=3 vol=6 ((c+b)'(c'a')')'((c+b)d)' + +Class 35. Func 33. Functions = 4. Volume = 13. 0000000100111110 + 830 : 0x013e tt=0000000100111110 lev=3 vol=6 ((cb)'d')+((b'a')c') + 833 : 0x013e tt=0000000100111110 lev=3 vol=6 ((cb)'d')+((c'a')b') + 883 : 0x013e tt=0000000100111110 lev=3 vol=6 ((c'b')a')+((cb)'d') + 1695 : 0x013e tt=0000000100111110 lev=4 vol=6 (((b'a')c')+d)'(cb)' + +Class 36. Func 34. Functions = 5. Volume = 22. 0000000100111111 + 1049 : 0x013f tt=0000000100111111 lev=3 vol=6 ((da)'(cb)')((c'b')'d)' + 1171 : 0x013f tt=0000000100111111 lev=3 vol=6 ((db)'(cb)')((c'a')'d)' + 1233 : 0x013f tt=0000000100111111 lev=3 vol=5 ((d'b')'c)'((b'a')'d)' + 1402 : 0x013f tt=0000000100111111 lev=3 vol=5 ((d'c')'b)'((c'a')'d)' + 1678 : 0x013f tt=0000000100111111 lev=4 vol=5 (((b'a')c')'d)'(cb)' + +Class 37. Func 35. Functions = 10. Volume = 25. 0000000101101000 + 727 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((b+a)+c)'((b'a')+d)' + 784 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c'a')+d)'((b+a)+c)' + 800 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+a)+b)'((b'a')+d)' + 803 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+a)+b)'((c'a')+d)' + 925 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c'b')+d)'((b+a)+c)' + 932 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c'b')+d)'((c+a)+b)' + 964 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+b)+a)'((b'a')+d)' + 967 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+b)+a)'((c'a')+d)' + 970 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+b)+a)'((c'b')+d)' + 1574 : 0x0168 tt=0000000101101000 lev=4 vol=8 (((ba)'d')+c)'((b'a')+d)' + +Class 38. Func 36. Functions = 9. Volume = 21. 0000000101101001 + 726 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((b+a)+c)'((b'a')'d)' + 775 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c'a')'d)'((b+a)+c)' + 799 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+a)+b)'((b'a')'d)' + 802 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+a)+b)'((c'a')'d)' + 900 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c'b')'d)'((b+a)+c)' + 905 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c'b')'d)'((c+a)+b)' + 963 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+b)+a)'((b'a')'d)' + 966 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+b)+a)'((c'a')'d)' + 969 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+b)+a)'((c'b')'d)' + +Class 42. Func 37. Functions = 1. Volume = 5. 0000000101101111 + 715 : 0x016f tt=0000000101101111 lev=3 vol=6 ((b+a)'c)'((b'a')'d)' + +Class 44. Func 38. Functions = 10. Volume = 39. 0000000101111111 + 1481 : 0x017f tt=0000000101111111 lev=4 vol=8 (((ba)c)'d')+((da')(c'b')) + 1482 : 0x017f tt=0000000101111111 lev=4 vol=8 (((ba)c)'d')+((db')(c'a')) + 1483 : 0x017f tt=0000000101111111 lev=4 vol=8 (((ba)c)'d')+((dc')(b'a')) + 1486 : 0x017f tt=0000000101111111 lev=4 vol=7 (((ba)c)'(da)')((c'b')'d)' + 1488 : 0x017f tt=0000000101111111 lev=4 vol=7 (((ba)c)'(db)')((c'a')'d)' + 1490 : 0x017f tt=0000000101111111 lev=4 vol=7 (((ba)c)'(dc)')((b'a')'d)' + 1569 : 0x017f tt=0000000101111111 lev=4 vol=6 (((ba)'d')'c)'((b'a')'d)' + 1680 : 0x017f tt=0000000101111111 lev=4 vol=6 (((b'a')c')'d)'((ba)c)' + 1684 : 0x017f tt=0000000101111111 lev=4 vol=6 (((b'a')c')'d)'((ca)b)' + 1687 : 0x017f tt=0000000101111111 lev=4 vol=6 (((b'a')c')'d)'((cb)a)' + +Class 45. Func 39. Functions = 106. Volume = 249. 0000000110000000 + 814 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+a)'(b+a)')(d+a) + 816 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+a)'(b+a)')(d+b) + 818 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+a)'(b+a)')(d+c) + 992 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(b+a)')(d+a) + 994 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(b+a)')(d+b) + 996 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(b+a)')(d+c) + 1008 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(c+a)')(d+a) + 1010 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(c+a)')(d+b) + 1012 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(c+a)')(d+c) + 1099 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((da')'(cb)')'((d'a)'(c'b')')' + 1169 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(c'a)')((d'a')'(cb')') + 1170 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(ca')')((da')'(cb)')' + 1176 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(cb')')((da')'(ca)')' + 1177 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(cb')')((d'a')'(c'a)') + 1185 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(d'a')')((cb)'(c'a')')' + 1186 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(d'a')')((cb')'(c'a)') + 1201 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(c'a')')'((d'a')'(c'b)') + 1206 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(c'b')')'((da')'(ca)')' + 1207 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(c'b')')'((d'a')'(c'a)') + 1209 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(da')')'((c'b)'(ca')') + 1210 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(da')')'((c'b')'(ca)')' + 1218 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(ca)')'((da)'(cb')') + 1219 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(ca)')'((d'b)'(c'a')')' + 1222 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(cb)')'((da)'(ca')') + 1223 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(cb)')'((d'a)'(c'a')')' + 1225 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(d'a)')'((cb)'(c'a')')' + 1226 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(d'a)')'((cb')'(c'a)') + 1245 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(c'a)')((d'a)'(c'b')')' + 1248 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(ca')')((da)'(c'b)') + 1254 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(c'b)')((da)'(ca')') + 1255 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(c'b)')((d'a)'(c'a')')' + 1256 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(da)')((c'b)'(ca')') + 1257 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(da)')((c'b')'(ca)')' + 1309 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(b'a)')((d'a')'(c'b)') + 1310 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(b'a)')((db')'(ca)')' + 1312 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(ba')')((da')'(cb)')' + 1314 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(ba')')((d'b')'(c'a)') + 1317 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(c'a)')((db')'(ba)')' + 1318 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(c'a)')((d'b')'(ba')') + 1323 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(c'b)')((da')'(ba)')' + 1324 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(c'b)')((d'a')'(b'a)') + 1335 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(d'a')')((cb)'(b'a')')' + 1336 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(d'a')')((c'b)'(b'a)') + 1340 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(d'b')')((ca)'(b'a')')' + 1341 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(d'b')')((c'a)'(ba')') + 1353 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(b'a')')'((d'a')'(cb')') + 1354 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(b'a')')'((d'b')'(ca')') + 1356 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(c'a')')'((db')'(ba)')' + 1357 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(c'a')')'((d'b')'(ba')') + 1359 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(c'b')')'((da')'(ba)')' + 1360 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(c'b')')'((d'a')'(b'a)') + 1362 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(da')')'((cb')'(ba')') + 1363 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(da')')'((c'b')'(ba)')' + 1365 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(db')')'((ca')'(b'a)') + 1366 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(db')')'((c'a')'(ba)')' + 1374 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ba)')'((da)'(c'b)') + 1375 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ba)')'((db)'(c'a)') + 1376 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ba)')'((d'c)'(b'a')')' + 1381 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ca)')'((db)'(b'a)') + 1382 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ca)')'((d'b)'(b'a')')' + 1384 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(cb)')'((da)'(ba')') + 1385 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(cb)')'((d'a)'(b'a')')' + 1386 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(d'a)')'((cb)'(b'a')')' + 1387 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(d'a)')'((c'b)'(b'a)') + 1389 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(d'b)')'((ca)'(b'a')')' + 1390 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(d'b)')'((c'a)'(ba')') + 1413 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(b'a)')((d'a)'(c'b')')' + 1414 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(b'a)')((db)'(ca')') + 1416 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(ba')')((da)'(cb')') + 1417 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(ba')')((d'b)'(c'a')')' + 1436 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(ca')')((db)'(b'a)') + 1437 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(ca')')((d'b)'(b'a')')' + 1439 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(cb')')((da)'(ba')') + 1440 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(cb')')((d'a)'(b'a')')' + 1441 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(da)')((cb')'(ba')') + 1442 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(da)')((c'b')'(ba)')' + 1444 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(db)')((ca')'(b'a)') + 1445 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(db)')((c'a')'(ba)')' + 1487 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)c)'(da')')'((c'b')'d)' + 1489 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)c)'(db')')'((c'a')'d)' + 1491 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)c)'(dc')')'((b'a')'d)' + 1501 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'c)'(da)')((db')'c')' + 1505 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'c)'(db)')((da')'c')' + 1507 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'c)'(d'c')')((b'a')'d)' + 1560 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)d')'(c'a')')'((db')'c')' + 1563 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)d')'(c'b')')'((da')'c')' + 1566 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)d')'(dc')')'((b'a')'c')' + 1576 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'d')'(c'a)')((c'b')'d)' + 1579 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'d')'(c'b)')((c'a')'d)' + 1581 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'d')'(dc)')((b'a')'c')' + 1703 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')c')'(d'a)')'((cb)'d')' + 1704 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')c')'(d'b)')'((ca)'d')' + 1707 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')c')'(d'c)')'((ba)'d')' + 1709 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')c')'((ba)d')')'(d'c')' + 1720 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'c')'(d'a')')((d'b)'c)' + 1723 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'c')'(d'b')')((d'a)'c)' + 1724 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'c')'(dc)')((ba)'d')' + 1729 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'c')'((ba)'d')')(dc)' + 1736 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')d)'(ca)')'((d'b)'c)' + 1737 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')d)'(cb)')'((d'a)'c)' + 1739 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')d)'(d'c)')'((ba)'c)' + 1740 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')d)'((ba)c)')'(dc)' + 1746 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'d)'(ca')')((cb)'d')' + 1752 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'d)'(cb')')((ca)'d')' + 1755 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'d)'(d'c')')((ba)'c)' + 1756 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'d)'((ba)'c)')(d'c')' + +Class 46. Func 40. Functions = 46. Volume = 109. 0000000110000001 + 813 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+a)'(b+a)')(da)' + 815 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+a)'(b+a)')(db)' + 817 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+a)'(b+a)')(dc)' + 991 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(b+a)')(da)' + 993 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(b+a)')(db)' + 995 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(b+a)')(dc)' + 1007 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(c+a)')(da)' + 1009 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(c+a)')(db)' + 1011 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(c+a)')(dc)' + 1027 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(b'a)')((c'b)'(ca')') + 1029 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(b'a)')((c'b')'(ca)')' + 1033 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(ba')')((cb)'(c'a')')' + 1034 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(ba')')((cb')'(c'a)') + 1036 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(b+a)')(c+a)' + 1038 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(b+a)')(c+b)' + 1040 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c'a)')((cb')'(ba')') + 1041 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c'a)')((c'b')'(ba)')' + 1044 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(ca')')((cb)'(b'a')')' + 1045 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(ca')')((c'b)'(b'a)') + 1047 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c+a)')(b+a)' + 1048 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c+a)')(c+b)' + 1052 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c'b)')((ca')'(b'a)') + 1053 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c'b)')((c'a')'(ba)')' + 1057 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(cb')')((ca)'(b'a')')' + 1058 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(cb')')((c'a)'(ba')') + 1062 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c+b)')(b+a)' + 1064 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c+b)')(c+a)' + 1070 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((d'a)'b)'((c+a)'(b'a)') + 1071 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'b)'((cb)'(c'a')')' + 1072 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'b)'((cb')'(c'a)') + 1075 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'c)'((cb)'(b'a')')' + 1076 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'c)'((c'b)'(b'a)') + 1088 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'(c'b')')'((cb)'a)' + 1188 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'a)'((c'b)'(ca')') + 1190 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'a)'((c'b')'(ca)')' + 1193 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'c)'((ca)'(b'a')')' + 1194 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'c)'((c'a)'(ba')') + 1200 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'(c'a')')'((ca)'b)' + 1343 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'a)'((cb')'(ba')') + 1344 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'a)'((c'b')'(ba)')' + 1347 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'b)'((ca')'(b'a)') + 1348 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'b)'((c'a')'(ba)')' + 1352 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'(b'a')')'((ba)'c)' + 1554 : 0x0181 tt=0000000110000001 lev=4 vol=6 (((ba)d')'c)'((b'a')'c')' + 1559 : 0x0181 tt=0000000110000001 lev=4 vol=6 (((ba)d')'(c'a')')'(c'b)' + 1562 : 0x0181 tt=0000000110000001 lev=4 vol=6 (((ba)d')'(c'b')')'(c'a)' + +Class 47. Func 41. Functions = 28. Volume = 81. 0000000110000010 + 983 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((c+b)'(ba')')(d+a) + 999 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((c+b)'(ca')')(d+a) + 1125 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d'a')'(c+b)')((b'a')'d)' + 1126 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d'a')'(c+b)')((c'a')'d)' + 1133 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(ba')')(c+b)' + 1136 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(ca')')(c+b)' + 1139 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c'b)')((ba)'c)' + 1140 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(cb')')((ca)'b)' + 1142 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c+b)')(ba')' + 1143 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c+b)')(ca')' + 1144 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c+b)')(db)' + 1145 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c+b)')(dc)' + 1180 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((db)'(c+b)')(d+a) + 1187 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((db)'(d+a))(c+b)' + 1196 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d'b)'c)'((d+a)(c'b)') + 1212 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((db')'a')'((da)'(c+b)') + 1328 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((dc)'(c+b)')(d+a) + 1337 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((dc)'(d+a))(c+b)' + 1349 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d'c)'b)'((d+a)(cb')') + 1368 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((dc')'a')'((da)'(c+b)') + 1485 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba)c)'(c'b')')'(d+a) + 1499 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba)'c)'(c'b)')(d+a) + 1504 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba)'c)'(d+a))(c'b)' + 1629 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba')'c)+b)'(d+a) + 1649 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba')'d)+a)(c+b)' + 1738 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((b'a')d)'(d'a)')'(c+b)' + 1753 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((b'a')'d)'(c+b)')(d'a')' + 1754 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((b'a')'d)'(d'a')')(c+b)' + +Class 48. Func 42. Functions = 14. Volume = 43. 0000000110000011 + 982 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((c+b)'(ba')')(da)' + 998 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((c+b)'(ca')')(da)' + 1031 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(ba')')(c+b)' + 1043 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(ca')')(c+b)' + 1051 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(c'b)')((ba)'c)' + 1056 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(cb')')((ca)'b)' + 1061 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(c+b)')(ba')' + 1063 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(c+b)')(ca')' + 1078 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((d'a)'(b'a')')'(c+b)' + 1079 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((d'a)'(c'a')')'(c+b)' + 1484 : 0x0183 tt=0000000110000011 lev=4 vol=6 (((ba)c)'(c'b')')'(da)' + 1498 : 0x0183 tt=0000000110000011 lev=4 vol=6 (((ba)'c)'(c'b)')(da)' + 1500 : 0x0183 tt=0000000110000011 lev=4 vol=6 (((ba)'c)'(da)')(c'b)' + 1628 : 0x0183 tt=0000000110000011 lev=4 vol=6 (((ba')'c)+b)'(da)' + +Class 49. Func 43. Functions = 1. Volume = 5. 0000000110000110 + 710 : 0x0186 tt=0000000110000110 lev=3 vol=7 ((b'a')+d)'((ba)+c)' + +Class 51. Func 44. Functions = 22. Volume = 56. 0000000110001001 + 648 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((b'a')c')+((ba)d') + 764 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((ca')'(b+a)')(da)' + 765 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((ca')'(b+a)')(db)' + 770 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((c'a')b')+((ba)d') + 869 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((cb')'(b+a)')(da)' + 870 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((cb')'(b+a)')(db)' + 882 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((c'b')a')+((ba)d') + 1019 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'b)+((cb')'a') + 1028 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(b'a)')((c'b')'a')' + 1032 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(ba')')((c'a')'b')' + 1035 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(b+a)')(ca')' + 1037 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(b+a)')(cb')' + 1042 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(ca')')(b+a)' + 1055 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(cb')')(b+a)' + 1065 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((d'a)b)+((b'a')c') + 1066 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((d'a)b)+((c'a')b') + 1067 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((d'a)b)+((c'b')a') + 1068 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((d'a)'b)'((ca')'(b'a)') + 1069 : 0x0189 tt=0000000110001001 lev=3 vol=5 ((d'a)'b)'((c'a')'b')' + 1087 : 0x0189 tt=0000000110001001 lev=3 vol=5 ((d'a)'(c'b')')'(b'a)' + 1189 : 0x0189 tt=0000000110001001 lev=3 vol=5 ((d'b)'a)'((c'b')'a')' + 1199 : 0x0189 tt=0000000110001001 lev=3 vol=5 ((d'b)'(c'a')')'(ba')' + +Class 52. Func 45. Functions = 5. Volume = 17. 0000000110001011 + 868 : 0x018b tt=0000000110001011 lev=3 vol=5 ((cb')'(ba')')(da)' + 940 : 0x018b tt=0000000110001011 lev=3 vol=5 ((c'b')'(ba)')'(da)' + 1030 : 0x018b tt=0000000110001011 lev=3 vol=5 ((da)'(ba')')(cb')' + 1054 : 0x018b tt=0000000110001011 lev=3 vol=5 ((da)'(cb')')(ba')' + 1077 : 0x018b tt=0000000110001011 lev=3 vol=5 ((d'a)'(b'a')')'(cb')' + +Class 53. Func 46. Functions = 1. Volume = 5. 0000000110001111 + 685 : 0x018f tt=0000000110001111 lev=3 vol=5 ((b'a')'d)'((ba)'c)' + +Class 56. Func 47. Functions = 4. Volume = 13. 0000000110011000 + 736 : 0x0198 tt=0000000110011000 lev=3 vol=7 ((b+a)'d')+((b'a')c') + 771 : 0x0198 tt=0000000110011000 lev=3 vol=7 ((c'a')b')+((b+a)'d') + 782 : 0x0198 tt=0000000110011000 lev=3 vol=6 ((c'a')+d)'(b+a)' + 918 : 0x0198 tt=0000000110011000 lev=3 vol=6 ((c'b')+d)'(b+a)' + +Class 57. Func 48. Functions = 2. Volume = 7. 0000000110011001 + 774 : 0x0199 tt=0000000110011001 lev=3 vol=5 ((c'a')'d)'(b+a)' + 894 : 0x0199 tt=0000000110011001 lev=3 vol=5 ((c'b')'d)'(b+a)' + +Class 59. Func 49. Functions = 7. Volume = 28. 0000000110011011 + 779 : 0x019b tt=0000000110011011 lev=3 vol=7 ((c'a')'d)'((c'a)'(b+a))' + 944 : 0x019b tt=0000000110011011 lev=3 vol=7 ((c'b')'(b+a))'((c'a')'d)' + 1118 : 0x019b tt=0000000110011011 lev=3 vol=7 ((d'a')'(cb'))'((da)'(ba')') + 1119 : 0x019b tt=0000000110011011 lev=3 vol=7 ((d'a')'(cb'))'((d'a)'(b'a')')' + 1583 : 0x019b tt=0000000110011011 lev=4 vol=7 (((b'a)c)'(ba')')((c'a')'d)' + 1615 : 0x019b tt=0000000110011011 lev=4 vol=7 (((b'a)'d')'c)'((da)'(ba')') + 1616 : 0x019b tt=0000000110011011 lev=4 vol=7 (((b'a)'d')'c)'((d'a)'(b'a')')' + +Class 62. Func 50. Functions = 6. Volume = 20. 0000000110101000 + 861 : 0x01a8 tt=0000000110101000 lev=3 vol=8 ((c'b)+(c+a))'(d+a) + 873 : 0x01a8 tt=0000000110101000 lev=3 vol=8 ((cb')+(b+a))'(d+a) + 888 : 0x01a8 tt=0000000110101000 lev=3 vol=6 ((c'b')+a)(d+a) + 920 : 0x01a8 tt=0000000110101000 lev=3 vol=6 ((c'b')+d)'(d+a) + 939 : 0x01a8 tt=0000000110101000 lev=3 vol=6 ((c'b')+d)'((c'b')+a) + 1100 : 0x01a8 tt=0000000110101000 lev=3 vol=6 ((da')'(c'b'))'((d'a)'(c'b')')' + +Class 63. Func 51. Functions = 5. Volume = 18. 0000000110101001 + 860 : 0x01a9 tt=0000000110101001 lev=3 vol=7 ((c'b)+(c+a))'(da)' + 872 : 0x01a9 tt=0000000110101001 lev=3 vol=7 ((cb')+(b+a))'(da)' + 887 : 0x01a9 tt=0000000110101001 lev=3 vol=5 ((c'b')+a)(da)' + 913 : 0x01a9 tt=0000000110101001 lev=3 vol=5 ((c'b')'d)'((c'b')+a) + 1089 : 0x01a9 tt=0000000110101001 lev=3 vol=5 ((d'a)'(c'b')')'((c'b')a)' + +Class 64. Func 52. Functions = 6. Volume = 24. 0000000110101010 + 761 : 0x01aa tt=0000000110101010 lev=3 vol=6 ((ca')'(ba')')(d+a) + 885 : 0x01aa tt=0000000110101010 lev=3 vol=5 ((c'b')'a')'(d+a) + 897 : 0x01aa tt=0000000110101010 lev=3 vol=5 ((c'b')'d)'(d+a) + 1211 : 0x01aa tt=0000000110101010 lev=3 vol=5 ((db')'a')'((c'a')'d)' + 1367 : 0x01aa tt=0000000110101010 lev=3 vol=5 ((dc')'a')'((b'a')'d)' + 1679 : 0x01aa tt=0000000110101010 lev=4 vol=5 (((b'a')c')'d)'(d'a')' + +Class 65. Func 53. Functions = 5. Volume = 17. 0000000110101011 + 642 : 0x01ab tt=0000000110101011 lev=3 vol=5 ((b'a')c')+(d'a) + 760 : 0x01ab tt=0000000110101011 lev=3 vol=5 ((ca')'(ba')')(da)' + 769 : 0x01ab tt=0000000110101011 lev=3 vol=5 ((c'a')b')+(d'a) + 881 : 0x01ab tt=0000000110101011 lev=3 vol=5 ((c'b')a')+(d'a) + 884 : 0x01ab tt=0000000110101011 lev=3 vol=4 ((c'b')'a')'(da)' + +Class 66. Func 54. Functions = 13. Volume = 41. 0000000110101100 + 809 : 0x01ac tt=0000000110101100 lev=3 vol=8 ((c+a)(ba)')'((b'a')+d)' + 859 : 0x01ac tt=0000000110101100 lev=3 vol=8 ((c'b)'(c+a))'((b'a')+d)' + 934 : 0x01ac tt=0000000110101100 lev=3 vol=8 ((c'b')+d)'((c+a)(ba)')' + 937 : 0x01ac tt=0000000110101100 lev=3 vol=8 ((c'b')+d)'((c'b)'(c+a))' + 1046 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((da)'(ca')')((c'b')+d)' + 1059 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((da)'(c'b'))+((ca')'d') + 1080 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((d'a)'(c'a')')'((c'b')+d)' + 1263 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((d+b)'c')'((da)'(ca')') + 1264 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((d+b)'c')'((d'a)'(c'a')')' + 1398 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((d'c')'a')+((da)'(c'b')') + 1748 : 0x01ac tt=0000000110101100 lev=4 vol=7 (((b'a')'d)'(ca')')((c'b')d')' + 1749 : 0x01ac tt=0000000110101100 lev=4 vol=7 (((b'a')'d)'(ca')')((d'b')c')' + 1750 : 0x01ac tt=0000000110101100 lev=4 vol=7 (((b'a')'d)'(ca')')((d'c')b')' + +Class 67. Func 55. Functions = 17. Volume = 50. 0000000110101101 + 808 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((c+a)(ba)')'((b'a')'d)' + 858 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((c'b)'(c+a))'((b'a')'d)' + 907 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((c'b')'d)'((c+a)(ba)')' + 911 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((c'b')'d)'((c'b)'(c+a))' + 1350 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((d'c)'(b'a))'((db)'(ca')') + 1521 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((ba)'c')+a)((b'a')'d)' + 1522 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((ba)'c')+a)((c'b')'d)' + 1592 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)c')'(ca')')((b'a')'d)' + 1593 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)c')'(ca')')((c'b')'d)' + 1595 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)c')'(db)')((d'a)'c)' + 1598 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)'c')'(ca)')'((b'a')'d)' + 1599 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)'c')'(ca)')'((c'b')'d)' + 1721 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'c')(d'b)')'((d'a)'c)' + 1744 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'d)'(ca')')((b'a)c')' + 1745 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'d)'(ca')')((c'a)b')' + 1747 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'d)'(ca')')((c'b')a)' + 1759 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'d)'((b'a)c')')(ca')' + +Class 68. Func 56. Functions = 1. Volume = 4. 0000000110101110 + 708 : 0x01ae tt=0000000110101110 lev=3 vol=5 ((b'a')+d)'(ca')' + +Class 69. Func 57. Functions = 1. Volume = 4. 0000000110101111 + 679 : 0x01af tt=0000000110101111 lev=3 vol=4 ((b'a')'d)'(ca')' + +Class 73. Func 58. Functions = 8. Volume = 29. 0000000110111111 + 1246 : 0x01bf tt=0000000110111111 lev=3 vol=6 ((d'b')'(ca'))'((b'a')'d)' + 1415 : 0x01bf tt=0000000110111111 lev=3 vol=6 ((d'c')'(ba'))'((c'a')'d)' + 1652 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((ba')'d')'c)'((b'a')'d)' + 1661 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((ba')'d')'(c'a')')'(db)' + 1662 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((ba')'d')'(c'a')')'((ba')d)' + 1681 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((b'a')c')'d)'((ba')c)' + 1686 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((b'a')c')'d)'((ca')b)' + 1688 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((b'a')c')'d)'((cb)a')' + +Class 75. Func 59. Functions = 7. Volume = 25. 0000000111101001 + 1495 : 0x01e9 tt=0000000111101001 lev=4 vol=9 (((ba)'c)+(b+a))'((b'a')'d)' + 1496 : 0x01e9 tt=0000000111101001 lev=4 vol=9 (((ba)'c)+(b+a))'((c'a')'d)' + 1497 : 0x01e9 tt=0000000111101001 lev=4 vol=9 (((ba)'c)+(b+a))'((c'b')'d)' + 1529 : 0x01e9 tt=0000000111101001 lev=4 vol=8 (((ba)'c')'d')+((dc)'(b'a')) + 1539 : 0x01e9 tt=0000000111101001 lev=4 vol=7 (((ba)'c')+(b'a'))'((b'a')'d)' + 1735 : 0x01e9 tt=0000000111101001 lev=4 vol=7 (((b'a')+c)'(ba)')'((b'a')'d)' + 1758 : 0x01e9 tt=0000000111101001 lev=4 vol=7 (((b'a')'d)'((ba)'c')')+(b'a') + +Class 76. Func 60. Functions = 17. Volume = 52. 0000000111101010 + 763 : 0x01ea tt=0000000111101010 lev=3 vol=8 ((ca')+(ba'))'((b'a')+d)' + 783 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c'a')+d)'((b'a')+d)' + 789 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c'a')+(b'a'))'((b'a')+d)' + 791 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c'a')+(b'a'))'((c'a')+d)' + 955 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c+b)a')'((b'a')+d)' + 957 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c+b)a')'((c'a')+d)' + 1138 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((d+a)'(cb)')'((c'b')'d)' + 1258 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((d+b)'a')'((c'a')+d)' + 1447 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((d+c)'a')'((b'a')+d)' + 1689 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')c')'d)'((d'a')(cb)')' + 1760 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d)'((b'a')c)')((c'a')d')' + 1761 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d)'((b'a')c)')((d'a')c')' + 1762 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d)'((b'a')c)')((d'c')a')' + 1779 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d')'(c'a')')'((db')'(c'a'))' + 1781 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d')'((b'a')c')')'((c'a')d')' + 1782 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d')'((b'a')c')')'((d'a')c')' + 1783 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d')'((b'a')c')')'((d'c')a')' + +Class 77. Func 61. Functions = 8. Volume = 22. 0000000111101011 + 762 : 0x01eb tt=0000000111101011 lev=3 vol=7 ((ca')+(ba'))'((b'a')'d)' + 780 : 0x01eb tt=0000000111101011 lev=3 vol=7 ((c'a')'d)'((ca')+(ba'))' + 788 : 0x01eb tt=0000000111101011 lev=3 vol=6 ((c'a')+(b'a'))'((b'a')'d)' + 790 : 0x01eb tt=0000000111101011 lev=3 vol=6 ((c'a')+(b'a'))'((c'a')'d)' + 954 : 0x01eb tt=0000000111101011 lev=3 vol=6 ((c+b)a')'((b'a')'d)' + 956 : 0x01eb tt=0000000111101011 lev=3 vol=6 ((c+b)a')'((c'a')'d)' + 1751 : 0x01eb tt=0000000111101011 lev=4 vol=6 (((b'a')'d)'(c'a')')+(b'a') + 1778 : 0x01eb tt=0000000111101011 lev=4 vol=6 (((b'a')'d')'(c'a')')'((c'a')b)' + +Class 78. Func 62. Functions = 4. Volume = 14. 0000000111101110 + 709 : 0x01ee tt=0000000111101110 lev=3 vol=5 ((b'a')+d)'(dc)' + 712 : 0x01ee tt=0000000111101110 lev=3 vol=5 ((b'a')+d)'((b'a')c)' + 1377 : 0x01ee tt=0000000111101110 lev=3 vol=5 ((dc')'(b'a'))'((b'a')'d)' + 1683 : 0x01ee tt=0000000111101110 lev=4 vol=5 (((b'a')c')'d)'((b'a')d')' + +Class 79. Func 63. Functions = 1. Volume = 4. 0000000111101111 + 691 : 0x01ef tt=0000000111101111 lev=3 vol=4 ((b'a')'d)'((b'a')c)' + +Class 80. Func 64. Functions = 32. Volume = 70. 0000000111111110 + 662 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((b'a')'c')+(d+c) + 772 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((c'a')'b')+(d+b) + 886 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((c'b')'a')+(d+a) + 1023 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da)'d')+((b'a')c') + 1025 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da)'d')+((c'a')b') + 1026 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da)'d')+((c'b')a') + 1095 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da')'d')+((b'a')c') + 1097 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da')'d')+((c'a')b') + 1098 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da')'d')+((c'b')a') + 1141 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((d+a)'(c'b'))'((c'b')'d)' + 1162 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db)'d')+((b'a')c') + 1164 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db)'d')+((c'a')b') + 1165 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db)'d')+((c'b')a') + 1214 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db')'d')+((b'a')c') + 1216 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db')'d')+((c'a')b') + 1217 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db')'d')+((c'b')a') + 1271 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((d+b)'(c'a'))'((c'a')'d)' + 1295 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc)'d')+((b'a')c') + 1297 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc)'d')+((c'a')b') + 1298 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc)'d')+((c'b')a') + 1370 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc')'d')+((b'a')c') + 1372 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc')'d')+((c'a')b') + 1373 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc')'d')+((c'b')a') + 1456 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((d+c)'(b'a'))'((b'a')'d)' + 1690 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')'d)'((d'c')(b'a'))' + 1696 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')+d)'(da)' + 1697 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')+d)'(db)' + 1698 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')+d)'(dc)' + 1700 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')+d)'((b'a')'d)' + 1712 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')'c')+c)+d + 1717 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')'c')+d)+c + 1784 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')+d)c')'(dc)' + +Class 81. Func 65. Functions = 7. Volume = 21. 0000001100111100 + 826 : 0x033c tt=0000001100111100 lev=3 vol=6 ((cb)'d)+(c+b) + 828 : 0x033c tt=0000001100111100 lev=3 vol=5 ((cb)'d')+(c'b') + 919 : 0x033c tt=0000001100111100 lev=3 vol=5 ((c'b')+d)'(cb)' + 1160 : 0x033c tt=0000001100111100 lev=3 vol=5 ((db)'c')+(d'b') + 1237 : 0x033c tt=0000001100111100 lev=3 vol=5 ((d'b')+c)'(db)' + 1291 : 0x033c tt=0000001100111100 lev=3 vol=5 ((dc)'b')+(d'c') + 1405 : 0x033c tt=0000001100111100 lev=3 vol=5 ((d'c')+b)'(dc)' + +Class 82. Func 66. Functions = 8. Volume = 38. 0000001100111101 + 1085 : 0x033d tt=0000001100111101 lev=3 vol=8 ((d'a)'(c'b'))+((c+b)d') + 1120 : 0x033d tt=0000001100111101 lev=3 vol=7 ((d'a')'(c'b'))+((cb)'d') + 1249 : 0x033d tt=0000001100111101 lev=3 vol=7 ((d'b')(c'a')')+((db)'c') + 1421 : 0x033d tt=0000001100111101 lev=3 vol=7 ((d'c')(b'a')')+((dc)'b') + 1605 : 0x033d tt=0000001100111101 lev=4 vol=7 (((b'a)'c')'(d+c)')'((d+c)b)' + 1627 : 0x033d tt=0000001100111101 lev=4 vol=7 (((b'a)'d')'(d+c)')'((d+c)b)' + 1715 : 0x033d tt=0000001100111101 lev=4 vol=7 (((b'a')'c')d')+((dc)'b') + 1775 : 0x033d tt=0000001100111101 lev=4 vol=7 (((b'a')'d')c')+((dc)'b') + +Class 83. Func 67. Functions = 4. Volume = 15. 0000001100111111 + 893 : 0x033f tt=0000001100111111 lev=3 vol=6 ((c'b')d)+((cb)'d') + 896 : 0x033f tt=0000001100111111 lev=3 vol=4 ((c'b')'d)'(cb)' + 1232 : 0x033f tt=0000001100111111 lev=3 vol=4 ((d'b')'c)'(db)' + 1401 : 0x033f tt=0000001100111111 lev=3 vol=4 ((d'c')'b)'(dc)' + +Class 84. Func 68. Functions = 1. Volume = 3. 0000001101010110 + 292 : 0x0356 tt=0000001101010110 lev=2 vol=4 (d'a')+(c'b') + +Class 85. Func 69. Functions = 3. Volume = 12. 0000001101010111 + 901 : 0x0357 tt=0000001101010111 lev=3 vol=6 ((c'b')'d)'((ca)'(ba)') + 912 : 0x0357 tt=0000001101010111 lev=3 vol=4 ((c'b')'d)'((c'b')'a)' + 1109 : 0x0357 tt=0000001101010111 lev=3 vol=4 ((d'a')'c)'((d'a')'b)' + +Class 86. Func 70. Functions = 5. Volume = 15. 0000001101011000 + 933 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((c'b')+d)'((c+a)'d')' + 950 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((c'b')'(c+a)')'((c'b')+d)' + 1112 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((d'a')+c)'((c'b')+d)' + 1265 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((d+b)'c')'((d'a')+c)' + 1284 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((d+b)'(d'a')')'((d'a')+c)' + +Class 87. Func 71. Functions = 5. Volume = 17. 0000001101011001 + 805 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((c+a)d')+(c'b') + 1083 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((d'a)+(c'b))'(dc)' + 1261 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((d+b)c')+(d'a') + 1320 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((dc)'(c'b)')+(d'a) + 1334 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((dc)'(d'a)')+(c'b) + +Class 88. Func 72. Functions = 4. Volume = 14. 0000001101011010 + 892 : 0x035a tt=0000001101011010 lev=3 vol=7 ((c'b')d)+((c+a)d') + 906 : 0x035a tt=0000001101011010 lev=3 vol=6 ((c'b')'d)'((c+a)'d')' + 1111 : 0x035a tt=0000001101011010 lev=3 vol=5 ((d'a')+c)'(db)' + 1159 : 0x035a tt=0000001101011010 lev=3 vol=5 ((db)'c')+(d'a') + +Class 89. Func 73. Functions = 3. Volume = 14. 0000001101011011 + 908 : 0x035b tt=0000001101011011 lev=3 vol=7 ((c'b')'d)'((c+a)'(b'a')')' + 949 : 0x035b tt=0000001101011011 lev=3 vol=6 ((c'b')'(c+a)')'((c'b')'d)' + 1108 : 0x035b tt=0000001101011011 lev=3 vol=6 ((d'a')'c)'((d'a)'(c'b))' + +Class 91. Func 74. Functions = 3. Volume = 11. 0000001101011111 + 891 : 0x035f tt=0000001101011111 lev=3 vol=6 ((c'b')d)+((ca)'d') + 895 : 0x035f tt=0000001101011111 lev=3 vol=4 ((c'b')'d)'(ca)' + 1104 : 0x035f tt=0000001101011111 lev=3 vol=4 ((d'a')'c)'(db)' + +Class 92. Func 75. Functions = 3. Volume = 15. 0000001101101000 + 1094 : 0x0368 tt=0000001101101000 lev=3 vol=9 ((d'a)+(c+b))'((c'b')+d)' + 1117 : 0x0368 tt=0000001101101000 lev=3 vol=8 ((d'a')+(cb))'((c'b')+d)' + 1446 : 0x0368 tt=0000001101101000 lev=3 vol=8 ((d'c')'(d'b')')+((d'a')'(c'b')') + +Class 93. Func 76. Functions = 7. Volume = 24. 0000001101101001 + 1090 : 0x0369 tt=0000001101101001 lev=3 vol=8 ((d'a)+(c'b'))+((cb)d') + 1092 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((d'a)+(c+b))'(db)' + 1093 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((d'a)+(c+b))'(dc)' + 1161 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((db)'c')+((b+a)d') + 1179 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((db)'(c+b)')+(d'a) + 1293 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((dc)'b')+((c+a)d') + 1327 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((dc)'(c+b)')+(d'a) + +Class 96. Func 77. Functions = 4. Volume = 17. 0000001101101100 + 924 : 0x036c tt=0000001101101100 lev=3 vol=7 ((c'b')+d)'((b+a)'c)' + 1244 : 0x036c tt=0000001101101100 lev=3 vol=7 ((d'b')+(ca))'((c'b')'d)' + 1269 : 0x036c tt=0000001101101100 lev=3 vol=7 ((d+b)+(ca))(dc)' + 1292 : 0x036c tt=0000001101101100 lev=3 vol=6 ((dc)'b')+((ca)'d') + +Class 98. Func 78. Functions = 10. Volume = 44. 0000001101101110 + 1278 : 0x036e tt=0000001101101110 lev=3 vol=9 ((d+b)(cb')')+((d'a)(c'b)') + 1338 : 0x036e tt=0000001101101110 lev=3 vol=9 ((dc)+(d'b))+((d'a')'(c'b)') + 1342 : 0x036e tt=0000001101101110 lev=3 vol=9 ((dc)'(d+b))+((d'a)(c'b)') + 1391 : 0x036e tt=0000001101101110 lev=3 vol=8 ((dc')'(d'b')')+((d'a')'(c'b)') + 1570 : 0x036e tt=0000001101101110 lev=4 vol=8 (((ba)'d')'c)'((d+b)'(b'a)')' + 1571 : 0x036e tt=0000001101101110 lev=4 vol=8 (((ba)'d')'c)'((d+b)'(d'a)')' + 1617 : 0x036e tt=0000001101101110 lev=4 vol=8 (((b'a)'d')(ca)')+((dc)'b') + 1632 : 0x036e tt=0000001101101110 lev=4 vol=8 (((ba')'c)(d+b))'((d+b)'(b'a)')' + 1633 : 0x036e tt=0000001101101110 lev=4 vol=8 (((ba')'c)(d+b))'((d+b)'(d'a)')' + 1769 : 0x036e tt=0000001101101110 lev=4 vol=8 (((b'a')d')'((ba)c)')((c'b')'d)' + +Class 101. Func 79. Functions = 1. Volume = 6. 0000001101111101 + 1091 : 0x037d tt=0000001101111101 lev=3 vol=7 ((d'a)(c+b)')'((c'b')'d)' + +Class 103. Func 80. Functions = 18. Volume = 51. 0000001111000000 + 392 : 0x03c0 tt=0000001111000000 lev=2 vol=5 (d+b)(c+b)' + 488 : 0x03c0 tt=0000001111000000 lev=2 vol=5 (d+c)(c+b)' + 492 : 0x03c0 tt=0000001111000000 lev=2 vol=5 (d+c)(d+b) + 909 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((c'b')'d)'((cb)'d')' + 1172 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((db)'(cb')')(d'c')' + 1202 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'b)'(c'b')')'(d'c')' + 1213 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((db')'c')'((d'b)'c)' + 1221 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((db')'(cb)')'(dc)' + 1253 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'b')'(c'b)')(dc)' + 1321 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc)'(c'b)')(d'b')' + 1339 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc)'(d'b')')(c'b)' + 1358 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'c)'(c'b')')'(d'b')' + 1364 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'c)'(db')')'(cb')' + 1369 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc')'b')'((d'c)'b)' + 1383 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc')'(cb)')'(db)' + 1388 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc')'(d'b)')'(c'b)' + 1438 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'c')'(cb')')(db)' + 1443 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'c')'(db)')(cb')' + +Class 104. Func 81. Functions = 42. Volume = 109. 0000001111000001 + 1084 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'a)'(c'b'))+((cb)d') + 1181 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((db)'(c+b)')((b'a)d')' + 1182 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((db)'(c+b)')((c'a)d')' + 1183 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((db)'(c+b)')((d'a)b')' + 1184 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((db)'(c+b)')((d'a)c')' + 1191 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'b)c)+((d'a)'(c'b')) + 1230 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'b')a)'((db)'(c+b)') + 1267 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+b)'(b'a')')'(c+b)' + 1272 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+b)'(c'a')')'(c+b)' + 1283 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+b)'(d'a')')'(c+b)' + 1326 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c'b)')((d'b')(c'a')')' + 1329 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((b'a)d')' + 1330 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((c'a)d')' + 1331 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((d'a)b')' + 1332 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((d'a)c')' + 1333 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((d'b')a)' + 1345 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c)b)+((d'a)'(c'b')) + 1361 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c)'(c'b')')'((d'b')(c'a')')' + 1393 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c')a)'((db)'(c+b)') + 1394 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c')a)'((dc)'(c+b)') + 1419 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c')(b'a')')'((db)'(cb')') + 1420 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c')(b'a')')'((d'b)'(c'b')')' + 1457 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+c)'(b'a')')'(c+b)' + 1465 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+c)'(c'a')')'(c+b)' + 1473 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+c)'(d'a')')'(c+b)' + 1596 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)'c')'d')+((dc)'b') + 1606 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'c')+((dc)'b) + 1607 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(c'b)')((d'b)'c)' + 1608 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(cb')')((d'c)'b)' + 1610 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(c+b)')(db)' + 1611 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(c+b)')(dc)' + 1612 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(db)')(c+b)' + 1613 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(dc)')(c+b)' + 1624 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)'d')'(db')')'(c+b)' + 1625 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)'d')'(dc')')'(c+b)' + 1713 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'c')d')'((db)'(cb')') + 1714 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'c')d')'((d'b)'(c'b')')' + 1722 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'c')(db')')'((d'b)'c)' + 1772 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'d')+b)'(c+b)' + 1773 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'d')c')'((db)'(cb')') + 1774 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'d')c')'((d'b)'(c'b')')' + 1776 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'d')+c)'(c+b)' + +Class 105. Func 82. Functions = 4. Volume = 13. 0000001111000011 + 326 : 0x03c3 tt=0000001111000011 lev=2 vol=4 (db)'(c+b)' + 412 : 0x03c3 tt=0000001111000011 lev=2 vol=4 (dc)'(c+b)' + 1192 : 0x03c3 tt=0000001111000011 lev=3 vol=4 ((d'b)'c)'(c'b)' + 1346 : 0x03c3 tt=0000001111000011 lev=3 vol=4 ((d'c)'b)'(cb')' + +Class 108. Func 83. Functions = 15. Volume = 44. 0000001111000111 + 981 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((c+b)(ba')')'(db)' + 1000 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((c+b)(c'a')')'(db)' + 1173 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((db)'(cb')')((ba)c')' + 1174 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((db)'(cb')')((c'a)b)' + 1175 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((db)'(cb')')((c'b)a)' + 1195 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'c)'((d'a')'(c'b))' + 1197 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)(c'a)')+(c'b') + 1203 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'(c'b')')'((ba)c')' + 1204 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'(c'b')')'((c'a)b)' + 1205 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'(c'b')')'((c'b)a)' + 1208 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'(c'b')')'((d'b)(c'a))' + 1517 : 0x03c7 tt=0000001111000111 lev=4 vol=6 (((ba)c')'(cb')')(db)' + 1518 : 0x03c7 tt=0000001111000111 lev=4 vol=6 (((ba)c')'(db)')(cb')' + 1540 : 0x03c7 tt=0000001111000111 lev=4 vol=6 (((ba)'c')'(cb)')'(db)' + 1637 : 0x03c7 tt=0000001111000111 lev=4 vol=6 (((ba')'c')+b)(db)' + +Class 109. Func 84. Functions = 1. Volume = 3. 0000001111001111 + 325 : 0x03cf tt=0000001111001111 lev=2 vol=3 (db)'(cb')' + +Class 110. Func 85. Functions = 4. Volume = 17. 0000001111010100 + 927 : 0x03d4 tt=0000001111010100 lev=3 vol=8 ((c'b')+d)'((ca)+(ba))' + 929 : 0x03d4 tt=0000001111010100 lev=3 vol=8 ((c'b')+d)'((c'a)+(b'a))' + 953 : 0x03d4 tt=0000001111010100 lev=3 vol=7 ((c+b)a)'((c'b')+d)' + 1082 : 0x03d4 tt=0000001111010100 lev=3 vol=7 ((d'a)(cb)')'((c'b')+d)' + +Class 111. Func 86. Functions = 1. Volume = 6. 0000001111010101 + 1081 : 0x03d5 tt=0000001111010101 lev=3 vol=6 ((d'a)(cb)')'((c'b')'d)' + +Class 113. Func 87. Functions = 5. Volume = 19. 0000001111010111 + 902 : 0x03d7 tt=0000001111010111 lev=3 vol=7 ((c'b')'d)'((ca)+(ba))' + 904 : 0x03d7 tt=0000001111010111 lev=3 vol=7 ((c'b')'d)'((c'a)+(b'a))' + 952 : 0x03d7 tt=0000001111010111 lev=3 vol=6 ((c+b)a)'((c'b')'d)' + 1123 : 0x03d7 tt=0000001111010111 lev=3 vol=6 ((d'a')'(c+b))'(db)' + 1124 : 0x03d7 tt=0000001111010111 lev=3 vol=6 ((d'a')'(c+b))'(dc)' + +Class 114. Func 88. Functions = 20. Volume = 58. 0000001111011000 + 935 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((c'b')+d)'((c+a)'(b+a))' + 988 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((c+b)(b+a))'((c'b')+d)' + 1005 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((c+b)(c+a)')'((c'b')+d)' + 1452 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(ba)')'((d+b)'(b'a')')' + 1453 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(ba)')'((d+b)'(ca')')' + 1454 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(ba)')'((d+b)'(d'a')')' + 1461 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(c'a)')'((d+b)'(b'a')')' + 1462 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(c'a)')'((d+b)'(ca')')' + 1463 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(c'a)')'((d+b)'(d'a')')' + 1469 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(d'a)')'((d+b)'(b'a')')' + 1470 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(d'a)')'((d+b)'(ca')')' + 1471 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(d'a)')'((d+b)'(d'a')')' + 1502 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c)+(d'a'))'((c'b')+d)' + 1503 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c)+(d'a'))'((d+b)'(d'a')')' + 1532 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c')+d)'((d+b)'(b'a')')' + 1533 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c')+d)'((d+b)'(ca')')' + 1534 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c')+d)'((d+b)'(d'a')')' + 1545 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)+c)'(db)')+((ca)'d') + 1567 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)d')'(d'c')')+((d'a')'(c'b')') + 1578 : 0x03d8 tt=0000001111011000 lev=4 vol=7 (((ba)'d')(ca')')'((c'b')'d)' + +Class 115. Func 89. Functions = 10. Volume = 48. 0000001111011001 + 1279 : 0x03d9 tt=0000001111011001 lev=3 vol=9 ((d+b)(cb')')+((d'a')(cb)') + 1294 : 0x03d9 tt=0000001111011001 lev=3 vol=8 ((dc)+b)+((d'a)'(cb)') + 1322 : 0x03d9 tt=0000001111011001 lev=3 vol=8 ((dc)'(c'b)')+((d'a)(cb)') + 1506 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((ba)'c)'(d+b))+(d'a') + 1614 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((b'a)d')'(dc)')((d'a)'(c'b))' + 1626 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((b'a)'d')'(dc')')'((d'a)'(c'b))' + 1634 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((ba')c')'(dc)')((d+b)'a)' + 1636 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((ba')c')'((b'a)d')')((c'b')'d)' + 1643 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((ba')'c')'(d'c)')'((d+b)'a)' + 1777 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((b'a')'d')(c'a')')+((dc)'b') + +Class 117. Func 90. Functions = 11. Volume = 35. 0000001111011100 + 921 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((c'b')+d)'((b'a)c)' + 923 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((c'b')+d)'((b'a)d')' + 926 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((c'b')+d)'((ca)b')' + 938 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((c'b')+d)'((cb')a)' + 1074 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((d'a)b')'((c'b')+d)' + 1229 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((d'b')a)'((c'b')+d)' + 1247 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((d'b')(ca')')'((c'b')'d)' + 1270 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((d+b)'(ca')')'(dc)' + 1582 : 0x03dc tt=0000001111011100 lev=4 vol=6 (((b'a)c)'d')+(c'b') + 1609 : 0x03dc tt=0000001111011100 lev=4 vol=6 (((b'a)d')'(c'b')')+d + 1623 : 0x03dc tt=0000001111011100 lev=4 vol=6 (((b'a)'d')'(c'b')')'((c'b')d')' + +Class 118. Func 91. Functions = 4. Volume = 14. 0000001111011101 + 890 : 0x03dd tt=0000001111011101 lev=3 vol=6 ((c'b')d)+((b'a)'d') + 899 : 0x03dd tt=0000001111011101 lev=3 vol=5 ((c'b')'d)'((b'a)d')' + 1073 : 0x03dd tt=0000001111011101 lev=3 vol=5 ((d'a)b')'((c'b')'d)' + 1228 : 0x03dd tt=0000001111011101 lev=3 vol=5 ((d'b')a)'((c'b')'d)' + +Class 119. Func 92. Functions = 1. Volume = 4. 0000001111011110 + 593 : 0x03de tt=0000001111011110 lev=3 vol=5 ((b'a)'d')+(c'b') + +Class 120. Func 93. Functions = 7. Volume = 18. 0000001111111100 + 389 : 0x03fc tt=0000001111111100 lev=2 vol=5 (d+b)+(cb') + 486 : 0x03fc tt=0000001111111100 lev=2 vol=5 (d+c)+(c'b) + 849 : 0x03fc tt=0000001111111100 lev=3 vol=5 ((c'b)+c)+d + 850 : 0x03fc tt=0000001111111100 lev=3 vol=5 ((c'b)+d)+c + 862 : 0x03fc tt=0000001111111100 lev=3 vol=5 ((cb')+b)+d + 864 : 0x03fc tt=0000001111111100 lev=3 vol=5 ((cb')+d)+b + 915 : 0x03fc tt=0000001111111100 lev=3 vol=4 ((c'b')d')'((c'b')'d)' + +Class 121. Func 94. Functions = 1. Volume = 3. 0000011001100000 + 481 : 0x0660 tt=0000011001100000 lev=2 vol=5 (d+c)(b+a) + +Class 122. Func 95. Functions = 12. Volume = 35. 0000011001100001 + 1147 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+a)+(c+b))'((c'a')'(b+a)')' + 1148 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+a)+(c+b))'((c'b')'(b+a)')' + 1149 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+a)+(c+b))'((d'a')'(b+a)')' + 1242 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d'b')'(b+a)')'((d+a)+(c+b))' + 1274 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+b)+(c+a))'((c'a')'(b+a)')' + 1275 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+b)+(c+a))'((c'b')'(b+a)')' + 1276 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+b)+(c+a))'((d'a')'(b+a)')' + 1277 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+b)+(c+a))'((d'b')'(b+a)')' + 1306 : 0x0661 tt=0000011001100001 lev=3 vol=10 ((dc)'(ba)')((d+a)+(c+b))' + 1308 : 0x0661 tt=0000011001100001 lev=3 vol=10 ((dc)'(ba)')((d+b)+(c+a))' + 1411 : 0x0661 tt=0000011001100001 lev=3 vol=9 ((d'c')(ba)')+((dc)'(b+a)) + 1432 : 0x0661 tt=0000011001100001 lev=3 vol=8 ((d'c')+(b'a'))'((dc)'(ba)') + +Class 125. Func 96. Functions = 1. Volume = 3. 0000011001100110 + 407 : 0x0666 tt=0000011001100110 lev=2 vol=4 (dc)'(b+a) + +Class 127. Func 97. Functions = 4. Volume = 15. 0000011001101001 + 1146 : 0x0669 tt=0000011001101001 lev=3 vol=8 ((d+a)+(c+b))'(dc)' + 1273 : 0x0669 tt=0000011001101001 lev=3 vol=8 ((d+b)+(c+a))'(dc)' + 1316 : 0x0669 tt=0000011001101001 lev=3 vol=7 ((dc)'(b+a))+(d'c') + 1435 : 0x0669 tt=0000011001101001 lev=3 vol=7 ((d'c')+(b+a))(dc)' + +Class 129. Func 98. Functions = 6. Volume = 32. 0000011001101111 + 1178 : 0x066f tt=0000011001101111 lev=3 vol=10 ((db)'(cb')')+((d+a)(c+a)') + 1224 : 0x066f tt=0000011001101111 lev=3 vol=10 ((db')'(cb)')+((d+a)'(c+a)) + 1281 : 0x066f tt=0000011001101111 lev=3 vol=10 ((d+b)'(c+b))+((da')'(ca)') + 1282 : 0x066f tt=0000011001101111 lev=3 vol=10 ((d+b)(c+b)')+((da)'(ca')') + 1433 : 0x066f tt=0000011001101111 lev=3 vol=8 ((d'c')(b+a)')+((dc)'(b+a)) + 1434 : 0x066f tt=0000011001101111 lev=3 vol=6 ((d'c')'(b+a)')'(dc)' + +Class 132. Func 99. Functions = 8. Volume = 27. 0000011001110110 + 766 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((ca')'(b+a)')'(dc)' + 871 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((cb')'(b+a)')'(dc)' + 1301 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((dc)'(ba)')((b'a')c')' + 1302 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((dc)'(ba)')((c'a')b')' + 1303 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((dc)'(ba)')((c'b')a')' + 1702 : 0x0676 tt=0000011001110110 lev=4 vol=6 (((b'a')c')'(ba)')(dc)' + 1705 : 0x0676 tt=0000011001110110 lev=4 vol=6 (((b'a')c')'(dc)')(ba)' + 1725 : 0x0676 tt=0000011001110110 lev=4 vol=6 (((b'a')'c')'(d'c)')'(ba)' + +Class 137. Func 100. Functions = 9. Volume = 39. 0000011001111110 + 1524 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)'c')'d)'((c+a)'(b+a)')' + 1525 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)'c')'d)'((c+b)'(b+a)')' + 1526 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)'c')'d)'((c+b)'(c+a)')' + 1542 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)+c)d')+((b+a)c') + 1561 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)d')'(c'a')')+((d'c)'(c'b')') + 1564 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)d')'(c'b')')+((d'c)'(c'a')') + 1565 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)d')'(dc)')+((b+a)'c') + 1706 : 0x067e tt=0000011001111110 lev=4 vol=8 (((b'a')c')'(dc)')((d'c')'(ba))' + 1726 : 0x067e tt=0000011001111110 lev=4 vol=8 (((b'a')'c')'(d'c)')'((d'c')'(ba))' + +Class 138. Func 101. Functions = 8. Volume = 24. 0000011010010000 + 724 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((b+a)+c)(d+c) + 738 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((b+a)+d)'(d+c) + 740 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((b+a)+d)'((b+a)+c) + 797 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((c+a)+b)(d+c) + 961 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((c+b)+a)(d+c) + 1130 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((d+a)+b)'(d+c) + 1260 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((d+b)+a)'(d+c) + 1380 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((dc')'(b+a))'((d'c)'(b+a)')' + +Class 141. Func 102. Functions = 5. Volume = 16. 0000011010010110 + 723 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((b+a)+c)(dc)' + 730 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((b+a)'d)'((b+a)+c) + 796 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((c+a)+b)(dc)' + 960 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((c+b)+a)(dc)' + 1355 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((d'c)'(b+a)')'((b+a)c)' + +Class 142. Func 103. Functions = 8. Volume = 40. 0000011010010111 + 1509 : 0x0697 tt=0000011010010111 lev=4 vol=10 (((ba)c')'d')+((d+c)(b+a)) + 1543 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((ba)+c)(b'a')')'((b+a)'d)' + 1675 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')'c)+(ba))'((b+a)'d)' + 1716 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')'c')'d')+((dc)'(b+a)) + 1730 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')'c')'((b'a)'d')')'((c+a)b)' + 1731 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')'c')'((ba')'d')')'((c+b)a)' + 1741 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')d)'((b'a')'c)')+((dc)'(ba)) + 1766 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')d')'c')+((dc)'(b+a)') + +Class 143. Func 104. Functions = 1. Volume = 4. 0000011010011111 + 729 : 0x069f tt=0000011010011111 lev=3 vol=5 ((b+a)'d)'((b+a)c)' + +Class 145. Func 105. Functions = 7. Volume = 35. 0000011010110001 + 1544 : 0x06b1 tt=0000011010110001 lev=4 vol=10 (((ba)+c)'(d+a))+((dc)'b') + 1553 : 0x06b1 tt=0000011010110001 lev=4 vol=9 (((ba)'d)'(ca)')+((dc)'(b'a')') + 1577 : 0x06b1 tt=0000011010110001 lev=4 vol=9 (((ba)'d')+(c'a))+((dc)'b) + 1580 : 0x06b1 tt=0000011010110001 lev=4 vol=9 (((ba)'d')'(c'b)')+((d'b)'(c'a)') + 1650 : 0x06b1 tt=0000011010110001 lev=4 vol=8 (((ba')d')'(c'a)')+((c'b)'d) + 1718 : 0x06b1 tt=0000011010110001 lev=4 vol=8 (((b'a')'c')+d)'((c+a)b)' + 1719 : 0x06b1 tt=0000011010110001 lev=4 vol=8 (((b'a')'c')+d)'((d+a)'b)' + +Class 150. Func 106. Functions = 4. Volume = 16. 0000011010110110 + 1311 : 0x06b6 tt=0000011010110110 lev=3 vol=7 ((dc)'(ba')')+((b'a)'c') + 1597 : 0x06b6 tt=0000011010110110 lev=4 vol=7 (((b'a)'c')+(ba'))'(dc)' + 1645 : 0x06b6 tt=0000011010110110 lev=4 vol=7 (((ba')+c)'(b'a)')'(dc)' + 1653 : 0x06b6 tt=0000011010110110 lev=4 vol=7 (((ba')'d')'c)'((b+a)'c')' + +Class 154. Func 107. Functions = 2. Volume = 6. 0000011011110000 + 719 : 0x06f0 tt=0000011011110000 lev=3 vol=6 ((b+a)'c')'(d+c) + 728 : 0x06f0 tt=0000011011110000 lev=3 vol=6 ((b+a)'d)'(d+c) + +Class 156. Func 108. Functions = 14. Volume = 62. 0000011011110010 + 1137 : 0x06f2 tt=0000011011110010 lev=3 vol=10 ((d+a)'(c+a)')'((da')+(c'b))' + 1280 : 0x06f2 tt=0000011011110010 lev=3 vol=10 ((d+b)(c+b))'((db)+(c'a'))' + 1319 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((dc)'(c'a')')+((d'a')'(c'b)) + 1325 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((dc)'(c'b)')+((d'b)'(c'a')) + 1459 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((d+c)'(c'a)')'((b+a)'c')' + 1467 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((d+c)'(c'b')')'((b+a)'c')' + 1468 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((d+c)'(d'a)')'((b+a)'c')' + 1475 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((d+c)'(d'b')')'((b+a)'c')' + 1519 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba)c')'(dc)')((db)'(c'a'))' + 1541 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba)'c')'(d'c)')'((db)'(c'a'))' + 1638 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba')'c')'d)+((c'b)'(c'a')') + 1639 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba')'c')'d')+((b+a)c') + 1647 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba')d)'(dc)')+((b'a)'c') + 1648 : 0x06f2 tt=0000011011110010 lev=4 vol=7 (((ba')d)'((b'a)'c'))'(dc)' + +Class 157. Func 109. Functions = 2. Volume = 7. 0000011011110110 + 717 : 0x06f6 tt=0000011011110110 lev=3 vol=6 ((b+a)c')+(d'c) + 718 : 0x06f6 tt=0000011011110110 lev=3 vol=5 ((b+a)'c')'(dc)' + +Class 158. Func 110. Functions = 11. Volume = 42. 0000011011111001 + 720 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((b+a)'c')+(d+c) + 842 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((cb)'(c'a)')+(d+b) + 855 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((c'b)'(ca)')+(d+a) + 1024 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((da)'d')+((b+a)c') + 1096 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((da')'d')+((b+a)c') + 1163 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((db)'d')+((b+a)c') + 1215 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((db')'d')+((b+a)c') + 1296 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((dc)'d')+((b+a)c') + 1371 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((dc')'d')+((b+a)c') + 1458 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((d+c)'(b+a))'((b+a)'d)' + 1635 : 0x06f9 tt=0000011011111001 lev=4 vol=7 (((ba')c')'((b'a)c')')+d + +Class 159. Func 111. Functions = 7. Volume = 28. 0000011101110110 + 1305 : 0x0776 tt=0000011101110110 lev=3 vol=7 ((dc)'(ba)')((d'a')(c'b'))' + 1307 : 0x0776 tt=0000011101110110 lev=3 vol=7 ((dc)'(ba)')((d'b')(c'a'))' + 1418 : 0x0776 tt=0000011101110110 lev=3 vol=7 ((d'c')(b'a'))'((dc)'(ba)') + 1691 : 0x0776 tt=0000011101110110 lev=4 vol=7 (((b'a')c')d')'((dc)'(ba)') + 1727 : 0x0776 tt=0000011101110110 lev=4 vol=7 (((b'a')'c')'(d+c)')'(ba)' + 1765 : 0x0776 tt=0000011101110110 lev=4 vol=7 (((b'a')d')c')'((dc)'(ba)') + 1780 : 0x0776 tt=0000011101110110 lev=4 vol=7 (((b'a')'d')'(d+c)')'(ba)' + +Class 160. Func 112. Functions = 7. Volume = 22. 0000011101111000 + 1299 : 0x0778 tt=0000011101111000 lev=3 vol=7 ((dc)'(ba))+(d+c) + 1300 : 0x0778 tt=0000011101111000 lev=3 vol=6 ((dc)'(ba)')+(d'c') + 1412 : 0x0778 tt=0000011101111000 lev=3 vol=6 ((d'c')+(ba))'(dc)' + 1476 : 0x0778 tt=0000011101111000 lev=4 vol=6 (((ba)c)'d')+((ba)'c') + 1530 : 0x0778 tt=0000011101111000 lev=4 vol=6 (((ba)'c')+d)'((ba)c)' + 1548 : 0x0778 tt=0000011101111000 lev=4 vol=6 (((ba)d)'c')+((ba)'d') + 1573 : 0x0778 tt=0000011101111000 lev=4 vol=6 (((ba)'d')+c)'((ba)d)' + +Class 164. Func 113. Functions = 2. Volume = 7. 0000011110110000 + 792 : 0x07b0 tt=0000011110110000 lev=3 vol=6 ((c+a)b)'(d+c) + 1127 : 0x07b0 tt=0000011110110000 lev=3 vol=6 ((d+a)'b)'(d+c) + +Class 165. Func 114. Functions = 4. Volume = 21. 0000011110110001 + 1466 : 0x07b1 tt=0000011110110001 lev=3 vol=8 ((d+c)'(c'a')')'((d+a)'b)' + 1474 : 0x07b1 tt=0000011110110001 lev=3 vol=8 ((d+c)'(d'a')')'((d+a)'b)' + 1651 : 0x07b1 tt=0000011110110001 lev=4 vol=8 (((ba')d')'(dc)')((db')'(c'a))' + 1667 : 0x07b1 tt=0000011110110001 lev=4 vol=8 (((ba')'d')'(dc')')'((db')'(c'a))' + +Class 166. Func 115. Functions = 13. Volume = 44. 0000011110110100 + 1220 : 0x07b4 tt=0000011110110100 lev=3 vol=9 ((db')'(c'a)')+((d'a)'(c+b)') + 1304 : 0x07b4 tt=0000011110110100 lev=3 vol=8 ((dc)'(ba)')+((c+b)'d') + 1313 : 0x07b4 tt=0000011110110100 lev=3 vol=7 ((dc)'(ba')')+((db')'c') + 1547 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba)d)'c)+((d'b')'(ba)') + 1549 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba)d)'c')+((ba')'d') + 1646 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')+c)'(db')')'(dc)' + 1654 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((ba)c')' + 1655 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((ba)d)' + 1656 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((c'a)b)' + 1657 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((c'b)a)' + 1658 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((da)b)' + 1659 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((db)a)' + 1668 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')'((ba)c')')+c + +Class 169. Func 116. Functions = 1. Volume = 5. 0000011110111100 + 628 : 0x07bc tt=0000011110111100 lev=3 vol=6 ((ba')'d')+((ba)'c') + +Class 176. Func 117. Functions = 9. Volume = 28. 0000011111110000 + 520 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((ba)c')'(d+c) + 539 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((ba)d)'(d+c) + 753 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((c'a)b)'(d+c) + 845 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((c'b)a)'(d+c) + 1013 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((da)b)'(d+c) + 1150 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((db)a)'(d+c) + 1508 : 0x07f0 tt=0000011111110000 lev=4 vol=5 (((ba)c')'d)+c + 1523 : 0x07f0 tt=0000011111110000 lev=4 vol=5 (((ba)'c')'d)'(d'c')' + 1552 : 0x07f0 tt=0000011111110000 lev=4 vol=5 (((ba)'d)'c')'(dc)' + +Class 178. Func 118. Functions = 3. Volume = 15. 0000011111110010 + 756 : 0x07f2 tt=0000011111110010 lev=3 vol=6 ((c'a)'d')+((ba)'c') + 1460 : 0x07f2 tt=0000011111110010 lev=3 vol=6 ((d+c)'(c'a)')'((c'a)b)' + 1601 : 0x07f2 tt=0000011111110010 lev=4 vol=6 (((b'a)'c')(da')')'(dc)' + +Class 179. Func 119. Functions = 5. Volume = 17. 0000011111111000 + 522 : 0x07f8 tt=0000011111111000 lev=3 vol=6 ((ba)c')+(d+c) + 559 : 0x07f8 tt=0000011111111000 lev=3 vol=6 ((ba)+d)+((ba)'c) + 754 : 0x07f8 tt=0000011111111000 lev=3 vol=6 ((c'a)b)+(d+c) + 846 : 0x07f8 tt=0000011111111000 lev=3 vol=6 ((c'b)a)+(d+c) + 947 : 0x07f8 tt=0000011111111000 lev=3 vol=5 ((c'b')'(c'a')')+d + +Class 180. Func 120. Functions = 1. Volume = 1. 0000111111110000 + 34 : 0x0ff0 tt=0000111111110000 lev=1 vol=2 d+c + +Class 188. Func 121. Functions = 3. Volume = 12. 0001011010000011 + 1102 : 0x1683 tt=0001011010000011 lev=3 vol=9 ((da')+(c+b))'((d'a)'(cb))' + 1128 : 0x1683 tt=0001011010000011 lev=3 vol=9 ((d+a)'b)'((da')+(c+b))' + 1131 : 0x1683 tt=0001011010000011 lev=3 vol=9 ((d+a)'c)'((da')+(c+b))' + +Class 194. Func 122. Functions = 28. Volume = 50. 0001011010010110 + 725 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((b+a)+c)((ba)d)' + 745 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((ca)d)'((b+a)+c) + 798 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+a)+b)((ba)d)' + 801 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+a)+b)((ca)d)' + 824 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((cb)d)'((b+a)+c) + 825 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((cb)d)'((c+a)+b) + 962 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+b)+a)((ba)d)' + 965 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+b)+a)((ca)d)' + 968 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+b)+a)((cb)d)' + 1014 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)b)'((b+a)+c) + 1015 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)b)'((c+a)+b) + 1016 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)b)'((c+b)+a) + 1020 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)c)'((b+a)+c) + 1021 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)c)'((c+a)+b) + 1022 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)c)'((c+b)+a) + 1151 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)a)'((b+a)+c) + 1152 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)a)'((c+a)+b) + 1153 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)a)'((c+b)+a) + 1156 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)c)'((b+a)+c) + 1157 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)c)'((c+a)+b) + 1158 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)c)'((c+b)+a) + 1285 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)a)'((b+a)+c) + 1286 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)a)'((c+a)+b) + 1287 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)a)'((c+b)+a) + 1288 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)b)'((b+a)+c) + 1289 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)b)'((c+a)+b) + 1290 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)b)'((c+b)+a) + 1546 : 0x1696 tt=0001011010010110 lev=4 vol=7 (((ba)d)'c)+(b+a) + +Class 196. Func 123. Functions = 2. Volume = 11. 0001011010011000 + 1378 : 0x1698 tt=0001011010011000 lev=3 vol=9 ((dc')'(b+a))'((da)+(c'b'))' + 1379 : 0x1698 tt=0001011010011000 lev=3 vol=9 ((dc')'(b+a))'((db)+(c'a'))' + +Class 200. Func 124. Functions = 12. Volume = 43. 0001011010011110 + 1017 : 0x169e tt=0001011010011110 lev=3 vol=8 ((da)'b)+((c+a)(ba)') + 1018 : 0x169e tt=0001011010011110 lev=3 vol=8 ((da)'b)+((c'b)'(c+a)) + 1039 : 0x169e tt=0001011010011110 lev=3 vol=8 ((da)'(b+a)')+((ba)'c') + 1154 : 0x169e tt=0001011010011110 lev=3 vol=8 ((db)'a)+((c+b)(ba)') + 1155 : 0x169e tt=0001011010011110 lev=3 vol=8 ((db)'a)+((c+b)(c'a)') + 1166 : 0x169e tt=0001011010011110 lev=3 vol=8 ((db)'(b+a)')+((ba)'c') + 1492 : 0x169e tt=0001011010011110 lev=4 vol=8 (((ba)'c)+a)+((d'a)'b) + 1493 : 0x169e tt=0001011010011110 lev=4 vol=8 (((ba)'c)+b)+((d'b)'a) + 1494 : 0x169e tt=0001011010011110 lev=4 vol=7 (((ba)'c)+(b'a'))'((ba)d)' + 1550 : 0x169e tt=0001011010011110 lev=4 vol=7 (((ba)d)'(b'a')')+((ba)'c) + 1551 : 0x169e tt=0001011010011110 lev=4 vol=7 (((ba)d)'((ba)'c)')+(b'a') + 1733 : 0x169e tt=0001011010011110 lev=4 vol=7 (((b'a')+c)(ba)')'((ba)d)' + +Class 205. Func 125. Functions = 12. Volume = 48. 0001011011101001 + 752 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((ca)'(b+a)')+(d+c) + 810 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c+a)'(ba)')+(d+b) + 839 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((cb)'(b+a)')+(d+c) + 844 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((cb)'(c+a)')+(d+b) + 931 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c'b')+d)+((c'a')'(b'a')') + 943 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c'b')'(b'a')')+((c'a')+d) + 948 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c'b')'(c'a')')+((b'a')+d) + 980 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c+b)'(ba)')+(d+a) + 997 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c+b)'(ca)')+(d+a) + 1590 : 0x16e9 tt=0001011011101001 lev=4 vol=8 (((b'a)'c)'(c'a)')+(d+b) + 1631 : 0x16e9 tt=0001011011101001 lev=4 vol=8 (((ba')'c)'(c'b)')+(d+a) + 1771 : 0x16e9 tt=0001011011101001 lev=4 vol=8 (((b'a')d')'((b'a')'d)')+((ba)'c') + +Class 207. Func 126. Functions = 3. Volume = 11. 0001011110001110 + 1134 : 0x178e tt=0001011110001110 lev=3 vol=8 ((d+a)(b+a)')+((b+a)c') + 1135 : 0x178e tt=0001011110001110 lev=3 vol=7 ((d+a)'(b+a)')'((b+a)c)' + 1268 : 0x178e tt=0001011110001110 lev=3 vol=7 ((d+b)'(b+a)')'((b+a)c)' + +Class 212. Func 127. Functions = 11. Volume = 49. 0001011111101000 + 713 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((b+a)c)+((ba)+d) + 793 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c+a)b)+((ca)+d) + 851 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c'b)+d)+((c'a)'(b'a')') + 852 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c'b)'(b'a')')+((c'a)+d) + 865 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((cb')+d)+((c'a')'(b'a)') + 876 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((cb')'(c'a')')+((b'a)+d) + 942 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c'b')'(ba')')+((ca')+d) + 946 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c'b')'(ca')')+((ba')+d) + 951 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c+b)a)+((cb)+d) + 1510 : 0x17e8 tt=0001011111101000 lev=4 vol=8 (((ba)c')+d)+((b'a')'c) + 1537 : 0x17e8 tt=0001011111101000 lev=4 vol=6 (((ba)'c')'(b'a')')+d + +Class 213. Func 128. Functions = 11. Volume = 51. 0001100011100111 + 819 : 0x18e7 tt=0001100011100111 lev=3 vol=9 ((c+a)'(b+a)')+((b+a)+d) + 836 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((cb)+d)+((ca')'(ba)') + 854 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((c'b)'(b'a')')+((c'a')+d) + 857 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((c'b)'(ca')')+((ba')+d) + 867 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((cb')'(ba)')+((ca)+d) + 875 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((cb')'(c'a)')+((b'a)+d) + 930 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((c'b')+d)+((c'a)'(b'a')') + 1531 : 0x18e7 tt=0001100011100111 lev=4 vol=8 (((ba)'c')+d)+((b'a')'c) + 1588 : 0x18e7 tt=0001100011100111 lev=4 vol=8 (((b'a)'c)'(ba')')+(d+b) + 1630 : 0x18e7 tt=0001100011100111 lev=4 vol=8 (((ba')'c)'(b'a)')+(d+a) + 1670 : 0x18e7 tt=0001100011100111 lev=4 vol=7 (((b'a')c)'((ba)c')')+d + +Class 216. Func 129. Functions = 5. Volume = 19. 0001100111100110 + 739 : 0x19e6 tt=0001100111100110 lev=3 vol=8 ((b+a)+d)+((ba)c) + 742 : 0x19e6 tt=0001100111100110 lev=3 vol=8 ((ca)b)+((b+a)+d) + 743 : 0x19e6 tt=0001100111100110 lev=3 vol=6 ((ca)'b)+(d+a) + 821 : 0x19e6 tt=0001100111100110 lev=3 vol=6 ((cb)'a)+(d+b) + 1512 : 0x19e6 tt=0001100111100110 lev=4 vol=6 (((ba)c')'(b'a')')+d + +Class 218. Func 130. Functions = 4. Volume = 12. 0001101111100100 + 629 : 0x1be4 tt=0001101111100100 lev=3 vol=6 ((ba')+d)+(ca) + 748 : 0x1be4 tt=0001101111100100 lev=3 vol=6 ((ca)+d)+(ba') + 750 : 0x1be4 tt=0001101111100100 lev=3 vol=6 ((ca)+(ba'))+d + 758 : 0x1be4 tt=0001101111100100 lev=3 vol=5 ((c'a)'(b'a')')+d + +Class 219. Func 131. Functions = 3. Volume = 7. 0001111011100001 + 480 : 0x1ee1 tt=0001111011100001 lev=2 vol=5 (d+c)+(b'a') + 668 : 0x1ee1 tt=0001111011100001 lev=3 vol=5 ((b'a')+c)+d + 707 : 0x1ee1 tt=0001111011100001 lev=3 vol=5 ((b'a')+d)+c + +Class 220. Func 132. Functions = 15. Volume = 48. 0011110011000011 + 493 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((ba)'b')+(d+c) + 597 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((ba')'b')+(d+c) + 744 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((ca)'c')+(d+b) + 759 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((ca')'c')+(d+b) + 822 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((cb)'b')+(d+c) + 823 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((cb)'c')+(d+b) + 835 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((cb)+d)+(c'b') + 848 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((c'b)'b')+(d+c) + 863 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((cb')'c')+(d+b) + 877 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((cb')'(c'b)')+d + 976 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((c+b)d')'((c+b)'d)' + 1227 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((db')'(d'b)')+c + 1262 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((d+b)c')'((d+b)'c)' + 1392 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((dc')'(d'c)')+b + 1450 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((d+c)b')'((d+c)'b)' + +Class 221. Func 133. Functions = 15. Volume = 33. 0110100110010110 + 311 : 0x6996 tt=0110100110010110 lev=2 vol=6 (d+a)+(c+b) + 387 : 0x6996 tt=0110100110010110 lev=2 vol=6 (d+b)+(c+a) + 483 : 0x6996 tt=0110100110010110 lev=2 vol=6 (d+c)+(b+a) + 722 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((b+a)+c)+d + 737 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((b+a)+d)+c + 795 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((c+a)+b)+d + 807 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((c+a)+d)+b + 959 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((c+b)+a)+d + 977 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((c+b)+d)+a + 1129 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+a)+b)+c + 1132 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+a)+c)+b + 1259 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+b)+a)+c + 1266 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+b)+c)+a + 1449 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+c)+a)+b + 1451 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+c)+b)+a 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 index c4a23a89..a047af53 100644 --- a/regtest.script +++ b/regtest.script @@ -1,18 +1,103 @@ -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 +r examples/apex4.pla +resyn +sharem +fpga +cec +ps + +clp +share +resyn +map +cec +ps + +r examples/C2670.blif +resyn +fpga +cec +ps + +u +map +cec +ps + +r examples/frg2.blif +dsd +muxes +cec +clp +share +resyn +map +cec +ps + +r examples/pj1.blif +resyn +fpga +cec +ps + +u +map +cec +ps + +r examples/s38584.bench +resyn +fpga +cec +ps + +u +map +cec +ps + +r examples/ac.v +resyn +fpga +cec +ps + +u +map +cec +ps + +r examples/s444.blif +b +esd -v +dsd +cec +ps + +r examples/i10.blif +fpga +cec +ps +u +map +cec +ps + +r examples/i10.blif +b +fraig_store +resyn +fraig_store +resyn2 +fraig_store +fraig_restore +fpga +cec +ps + +u +map +cec +ps + time diff --git a/regtest_output.txt b/regtest_output.txt index 6e0ffec3..f66ee380 100644 --- a/regtest_output.txt +++ b/regtest_output.txt @@ -1,75 +1,110 @@ -UC Berkeley, ABC 1.01 (compiled Dec 25 2006 17:15:00) +UC Berkeley, ABC 1.01 (compiled Sep 5 2005 23:36:08) 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 +abc - > r examples/apex4.pla +abc - > resyn +abc - > sharem +abc - > fpga +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +examples/apex4.pla: i/o = 9/ 19 lat = 0 nd = 784 cube = 1985 lev = 5 +abc - > +abc - > clp +The shared BDD size is 917 nodes. +abc - > share +abc - > resyn +abc - > map 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 +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +examples/apex4.pla: i/o = 9/ 19 lat = 0 nd = 1816 area = 4599.00 delay = 11.50 lev = 11 +abc - > +abc - > r examples/C2670.blif +abc - > resyn +abc - > fpga +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +C2670.iscas : i/o = 233/ 140 lat = 0 nd = 169 cube = 482 lev = 6 +abc - > +abc - > u +abc - > map +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +C2670.iscas : i/o = 233/ 140 lat = 0 nd = 465 area = 1142.00 delay = 15.50 lev = 14 +abc - > +abc - > r examples/frg2.blif +abc - > dsd +abc - > muxes +abc - > cec +Networks are equivalent after fraiging. +abc - > clp +The shared BDD size is 1111 nodes. +abc - > share +abc - > resyn +abc - > map +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +frg2 : i/o = 143/ 139 lat = 0 nd = 540 area = 1360.00 delay = 10.10 lev = 9 +abc - > +abc - > r examples/pj1.blif +abc - > resyn +abc - > fpga +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +exCombCkt : i/o = 1769/1063 lat = 0 nd = 4730 cube = 10662 lev = 12 +abc - > +abc - > u +abc - > map +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +exCombCkt : i/o = 1769/1063 lat = 0 nd = 10396 area = 25170.00 delay = 29.20 lev = 27 +abc - > +abc - > r examples/s38584.bench +abc - > resyn +The network has 26 self-feeding latches. +abc - > fpga +abc - > cec +The network has 26 self-feeding latches. +The network has 26 self-feeding latches. +Networks are equivalent after fraiging. +abc - > ps +examples/s38584.bench: i/o = 12/ 278 lat = 1452 nd = 3239 cube = 6769 lev = 7 +abc - > +abc - > u +abc - > map +The network has 26 self-feeding latches. +abc - > cec +The network has 26 self-feeding latches. +The network has 26 self-feeding latches. +Networks are equivalent after fraiging. +abc - > ps +examples/s38584.bench: i/o = 12/ 278 lat = 1452 nd = 8522 area = 19305.00 delay = 20.60 lev = 17 +abc - > +abc - > r examples/ac.v +abc - > resyn +abc - > fpga +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +ac97_ctrl : i/o = 84/ 48 lat = 2199 nd = 3652 cube = 9391 lev = 3 +abc - > +abc - > u +abc - > map +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +ac97_ctrl : i/o = 84/ 48 lat = 2199 nd = 8337 area = 19861.00 delay = 8.10 lev = 8 +abc - > +abc - > r examples/s444.blif +abc - > b +abc - > esd -v 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. @@ -77,20 +112,54 @@ 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 +abc - > dsd +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +iscas\s444.bench: i/o = 3/ 6 lat = 21 nd = 81 cube = 119 lev = 7 +abc - > +abc - > r examples/i10.blif +abc - > fpga +The network was strashed and balanced before FPGA mapping. +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +i10 : i/o = 257/ 224 lat = 0 nd = 741 cube = 1616 lev = 11 +abc - > u +abc - > map +The network was strashed and balanced before mapping. +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +i10 : i/o = 257/ 224 lat = 0 nd = 1659 area = 4215.00 delay = 30.80 lev = 27 +abc - > +abc - > r examples/i10.blif +abc - > b +abc - > fraig_store +The number of AIG nodes added to storage = 2425. +abc - > resyn +abc - > fraig_store +The number of AIG nodes added to storage = 1678. +abc - > resyn2 +abc - > fraig_store +The number of AIG nodes added to storage = 1323. +abc - > fraig_restore +Currently stored 3 networks with 5426 nodes will be fraiged. +abc - > fpga +Performing FPGA mapping with choices. +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +i10 : i/o = 257/ 224 lat = 0 nd = 674 cube = 1498 lev = 10 +abc - > +abc - > u +abc - > map +Performing mapping with choices. +abc - > cec +Networks are equivalent after fraiging. +abc - > ps +i10 : i/o = 257/ 224 lat = 0 nd = 1505 area = 3561.00 delay = 25.00 lev = 22 +abc - > +abc 109> time +elapse: 77.52 seconds, total: 77.52 seconds +abc 109> \ No newline at end of file diff --git a/src/abc8/aig/aig.h b/src/abc8/aig/aig.h new file mode 100644 index 00000000..31e347ca --- /dev/null +++ b/src/abc8/aig/aig.h @@ -0,0 +1,619 @@ +/**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 "vec2.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; + +// 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 + Aig_Obj_t * pHaig; // pointer to the HAIG node + 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 + void * pManTime; // the timing manager + void * pManCuts; + Vec_Ptr_t * vMapped; + Vec_Int_t * vFlopNums; + void * pSeqModel; + Aig_Man_t * pManHaig; + // timing statistics + int time1; + int time2; +}; + +// cut computation +typedef struct Aig_ManCut_t_ Aig_ManCut_t; +typedef struct Aig_Cut_t_ Aig_Cut_t; + +// the cut used to represent node in the AIG +struct Aig_Cut_t_ +{ + Aig_Cut_t * pNext; // the next cut in the table + int 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 Aig_ManCut_t_ +{ + // AIG manager + Aig_Man_t * pAig; // the input AIG manager + Aig_Cut_t ** pCuts; // the cuts for each node in the output manager + // parameters + int nCutsMax; // the max number of cuts at the node + int nLeafMax; // the max number of leaves of a cut + int fTruth; // enables truth table computation + 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 +}; + +static inline Aig_Cut_t * Aig_ObjCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } +static inline void Aig_ObjSetCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; } + +static inline int Aig_CutLeaveNum( Aig_Cut_t * pCut ) { return pCut->nFanins; } +static inline int * Aig_CutLeaves( Aig_Cut_t * pCut ) { return pCut->pFanins; } +static inline unsigned * Aig_CutTruth( Aig_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); } +static inline Aig_Cut_t * Aig_CutNext( Aig_Cut_t * pCut ) { return (Aig_Cut_t *)(((char *)pCut) + pCut->nCutSize); } + +// iterator over cuts of the node +#define Aig_ObjForEachCut( p, pObj, pCut, i ) \ + for ( i = 0, pCut = Aig_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Aig_CutNext(pCut) ) +// iterator over leaves of the cut +#define Aig_CutForEachLeaf( p, pCut, pLeaf, i ) \ + for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// 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_Float2Int( float Val ) { return *((int *)&Val); } +static inline float Aig_Int2Float( int Num ) { return *((float *)&Num); } +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 int Aig_WordFindFirstBit( unsigned uWord ) +{ + int i; + for ( i = 0; i < 32; i++ ) + if ( uWord & (1 << i) ) + return i; + return -1; +} + +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 void Aig_ObjChild0Flip( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); pObj->pFanin0 = Aig_Not(pObj->pFanin0); } +static inline void Aig_ObjChild1Flip( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); pObj->pFanin1 = Aig_Not(pObj->pFanin1); } +static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level; } +static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(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 int Aig_ObjSetLevel( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level = i; } +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 Aig_Obj_t * Aig_ObjHaig( Aig_Obj_t * pObj ) { assert( Aig_Regular(pObj)->pHaig ); return Aig_NotCond( Aig_Regular(pObj)->pHaig, Aig_IsComplement(pObj) ); } +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 ); +/*=== aigCuts.c ========================================================*/ +extern Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ); +extern void Aig_ManCutStop( Aig_ManCut_t * p ); +/*=== aigDfs.c ==========================================================*/ +extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManDfsPio( 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 ); +/*=== aigFrames.c ==========================================================*/ +extern Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ); +/*=== aigHaig.c ==========================================================*/ +extern void Aig_ManHaigRecord( 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 Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize ); +extern Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize, int fVerbose ); +/*=== 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 ); +/*=== aigRetF.c ========================================================*/ +extern Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax ); +/*=== 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 ); +extern void Aig_TableClear( 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 ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/abc8/aig/aigCheck.c b/src/abc8/aig/aigCheck.c new file mode 100644 index 00000000..8c53e635 --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigCuts.c b/src/abc8/aig/aigCuts.c new file mode 100644 index 00000000..494d0d5b --- /dev/null +++ b/src/abc8/aig/aigCuts.c @@ -0,0 +1,669 @@ +/**CFile**************************************************************** + + FileName [aigCuts.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Computation of K-feasible priority cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigCuts.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the cut sweeping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_ManCut_t * Aig_ManCutStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ) +{ + Aig_ManCut_t * p; + assert( nCutsMax >= 2 ); + assert( nLeafMax <= 16 ); + // allocate the fraiging manager + p = ALLOC( Aig_ManCut_t, 1 ); + memset( p, 0, sizeof(Aig_ManCut_t) ); + p->nCutsMax = nCutsMax; + p->nLeafMax = nLeafMax; + p->fTruth = fTruth; + p->fVerbose = fVerbose; + p->pAig = pMan; + // allocate room for cuts and equivalent nodes + p->pCuts = ALLOC( Aig_Cut_t *, Aig_ManObjNumMax(pMan) ); + memset( p->pCuts, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pMan) ); + // allocate memory manager + p->nTruthWords = Aig_TruthWordNum(nLeafMax); + p->nCutSize = sizeof(Aig_Cut_t) + sizeof(int) * nLeafMax + fTruth * sizeof(unsigned) * p->nTruthWords; + p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 ); + // room for temporary truth tables + if ( fTruth ) + { + 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 Aig_ManCutStop( Aig_ManCut_t * p ) +{ + Aig_MmFixedStop( p->pMemCuts, 0 ); + FREE( p->puTemp[0] ); + free( p->pCuts ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Prints one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CutPrint( Aig_Cut_t * pCut ) +{ + int i; + printf( "{" ); + for ( i = 0; i < pCut->nFanins; i++ ) + printf( " %d", pCut->pFanins[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCutPrint( Aig_ManCut_t * p, Aig_Obj_t * pObj ) +{ + Aig_Cut_t * pCut; + int i; + printf( "Cuts for node %d:\n", pObj->Id ); + Aig_ObjForEachCut( p, pObj, pCut, i ) + if ( pCut->nFanins ) + Aig_CutPrint( pCut ); +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Computes the total number of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCutCount( Aig_ManCut_t * p, int * pnCutsK ) +{ + Aig_Cut_t * pCut; + Aig_Obj_t * pObj; + int i, k, nCuts = 0, nCutsK = 0; + Aig_ManForEachNode( p->pAig, pObj, i ) + Aig_ObjForEachCut( p, pObj, pCut, k ) + { + if ( pCut->nFanins == 0 ) + continue; + nCuts++; + if ( pCut->nFanins == p->nLeafMax ) + nCutsK++; + } + if ( pnCutsK ) + *pnCutsK = nCutsK; + return nCuts; +} + +/**Function************************************************************* + + Synopsis [Compute the cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_CutFindCost( Aig_ManCut_t * p, Aig_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + int i, Cost = 0; + assert( pCut->nFanins > 0 ); + Aig_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) + Cost += pLeaf->nRefs; + return Cost * 1000 / pCut->nFanins; +} + +/**Function************************************************************* + + Synopsis [Compute the cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Aig_CutFindCost2( Aig_ManCut_t * p, Aig_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + float Cost = 0.0; + int i; + assert( pCut->nFanins > 0 ); + Aig_CutForEachLeaf( p->pAig, 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 Aig_Cut_t * Aig_CutFindFree( Aig_ManCut_t * p, Aig_Obj_t * pObj ) +{ + Aig_Cut_t * pCut, * pCutMax; + int i; + pCutMax = NULL; + Aig_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 Aig_CutTruthPhase( Aig_Cut_t * pCut, Aig_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 * Aig_CutComputeTruth( Aig_ManCut_t * p, Aig_Cut_t * pCut, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + // permute the first table + if ( fCompl0 ) + Kit_TruthNot( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax ); + else + Kit_TruthCopy( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax ); + Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut0), 0 ); + // permute the second table + if ( fCompl1 ) + Kit_TruthNot( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax ); + else + Kit_TruthCopy( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax ); + Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut1), 0 ); + // produce the resulting table + Kit_TruthAnd( Aig_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax ); +// assert( pCut->nFanins >= Kit_TruthSupportSize( Aig_CutTruth(pCut), p->nLeafMax ) ); + return Aig_CutTruth(pCut); +} + +/**Function************************************************************* + + Synopsis [Performs support minimization for the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CutSupportMinimize( Aig_ManCut_t * p, Aig_Cut_t * pCut ) +{ + unsigned * pTruth; + int uSupp, nFansNew, i, k; + // get truth table + pTruth = Aig_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 Aig_CutCheckDominance( Aig_Cut_t * pDom, Aig_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 Aig_CutFilter( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCut ) +{ + Aig_Cut_t * pTemp; + int i; + // go through the cuts of the node + Aig_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 ( Aig_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 ( Aig_CutCheckDominance( pTemp, pCut ) ) + { + // remove the given + pCut->nFanins = 0; + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_CutMergeOrdered( Aig_ManCut_t * p, Aig_Cut_t * pC0, Aig_Cut_t * pC1, Aig_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 Aig_CutMerge( Aig_ManCut_t * p, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, Aig_Cut_t * pCut ) +{ + assert( p->nLeafMax > 0 ); + // merge the nodes + if ( pCut0->nFanins < pCut1->nFanins ) + { + if ( !Aig_CutMergeOrdered( p, pCut1, pCut0, pCut ) ) + return 0; + } + else + { + if ( !Aig_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) + return 0; + } + pCut->uSign = pCut0->uSign | pCut1->uSign; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Cut_t * Aig_ObjPrepareCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv ) +{ + Aig_Cut_t * pCutSet, * pCut; + int i; + // create the cutset of the node + pCutSet = (Aig_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); + Aig_ObjSetCuts( p, pObj, pCutSet ); + Aig_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 ); + if ( p->fTruth ) + memset( Aig_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords ); + } + return pCutSet; +} + +/**Function************************************************************* + + Synopsis [Derives cuts for one node and sweeps this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjComputeCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv ) +{ + Aig_Cut_t * pCut0, * pCut1, * pCut, * pCutSet; + Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); + Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); + int i, k; + // the node is not processed yet + assert( Aig_ObjIsNode(pObj) ); + assert( Aig_ObjCuts(p, pObj) == NULL ); + // set up the first cut + pCutSet = Aig_ObjPrepareCuts( p, pObj, fTriv ); + // compute pair-wise cut combinations while checking table + Aig_ObjForEachCut( p, pFanin0, pCut0, i ) + if ( pCut0->nFanins > 0 ) + Aig_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 = Aig_CutFindFree( p, pObj ); + // assemble the new cut + if ( !Aig_CutMerge( p, pCut0, pCut1, pCut ) ) + { + assert( pCut->nFanins == 0 ); + continue; + } + // check containment + if ( Aig_CutFilter( p, pObj, pCut ) ) + { + assert( pCut->nFanins == 0 ); + continue; + } + // create its truth table + if ( p->fTruth ) + Aig_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); + // assign the cost + pCut->Cost = Aig_CutFindCost( p, pCut ); + assert( pCut->nFanins > 0 ); + assert( pCut->Cost > 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for all nodes in the static AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ) +{ + Aig_ManCut_t * p; + Aig_Obj_t * pObj; + int i, clk = clock(); + assert( pAig->pManCuts == NULL ); + // start the manager + p = Aig_ManCutStart( pAig, nCutsMax, nLeafMax, fTruth, fVerbose ); + // set elementary cuts at the PIs + Aig_ManForEachPi( pAig, pObj, i ) + Aig_ObjPrepareCuts( p, pObj, 1 ); + // process the nodes + Aig_ManForEachNode( pAig, pObj, i ) + Aig_ObjComputeCuts( p, pObj, 1 ); + // print stats + if ( fVerbose ) + { + int nCuts, nCutsK; + nCuts = Aig_ManCutCount( p, &nCutsK ); + printf( "Nodes = %6d. Total cuts = %6d. %d-input cuts = %6d.\n", + Aig_ManObjNum(pAig), nCuts, nLeafMax, nCutsK ); + printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f Mb ", + p->nCutSize, 4*p->nTruthWords, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); + PRT( "Runtime", clock() - clk ); +/* + Aig_ManForEachNode( pAig, pObj, i ) + if ( i % 300 == 0 ) + Aig_ObjCutPrint( p, pObj ); +*/ + } + // remember the cut manager + pAig->pManCuts = p; + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/aig/aigDfs.c b/src/abc8/aig/aigDfs.c new file mode 100644 index 00000000..c7488487 --- /dev/null +++ b/src/abc8/aig/aigDfs.c @@ -0,0 +1,723 @@ +/**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_ManDfsPio( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); + Aig_ManForEachPo( p, pObj, i ) + 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/src/abc8/aig/aigFanout.c b/src/abc8/aig/aigFanout.c new file mode 100644 index 00000000..d0beb128 --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigFrames.c b/src/abc8/aig/aigFrames.c new file mode 100644 index 00000000..4a3b0c7c --- /dev/null +++ b/src/abc8/aig/aigFrames.c @@ -0,0 +1,133 @@ +/**CFile**************************************************************** + + FileName [aigFrames.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Performs timeframe expansion of the AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigFrames.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Aig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; } +static inline void Aig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; } + +static inline Aig_Obj_t * Aig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs timeframe expansion of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + Aig_Obj_t ** pObjMap; + int i, f; + + // create mapping for the frames nodes + pObjMap = ALLOC( Aig_Obj_t *, nFs * Aig_ManObjNumMax(pAig) ); + memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFs * Aig_ManObjNumMax(pAig) ); + + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFs ); + pFrames->pName = Aig_UtilStrsav( pAig->pName ); + // map constant nodes + for ( f = 0; f < nFs; f++ ) + Aig_ObjSetFrames( pObjMap, nFs, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); + // create PI nodes for the frames + for ( f = 0; f < nFs; f++ ) + Aig_ManForEachPiSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFs, pObj, f, Aig_ObjCreatePi(pFrames) ); + // set initial state for the latches + if ( fInit ) + { + Aig_ManForEachLoSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ManConst0(pFrames) ); + } + else + { + Aig_ManForEachLoSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ObjCreatePi(pFrames) ); + } + + // add timeframes + for ( f = 0; f < nFs; f++ ) + { +// printf( "Frame = %d.\n", f ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + { +// Aig_Obj_t * pFanin0 = Aig_ObjChild0Frames(pObjMap,nFs,pObj,f); +// Aig_Obj_t * pFanin1 = Aig_ObjChild1Frames(pObjMap,nFs,pObj,f); +// printf( "Node = %3d. Fanin0 = %3d. Fanin1 = %3d.\n", pObj->Id, Aig_Regular(pFanin0)->Id, Aig_Regular(pFanin1)->Id ); + pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f), Aig_ObjChild1Frames(pObjMap,nFs,pObj,f) ); + Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew ); + } + // set the latch inputs and copy them into the latch outputs of the next frame + Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) + { + pObjNew = Aig_ObjChild0Frames(pObjMap,nFs,pObjLi,f); + if ( f < nFs - 1 ) + Aig_ObjSetFrames( pObjMap, nFs, pObjLo, f+1, pObjNew ); + } + } + if ( fOuts ) + { + for ( f = fEnlarge?nFs-1:0; f < nFs; f++ ) + Aig_ManForEachPoSeq( pAig, pObj, i ) + { + pObjNew = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f) ); + Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew ); + } + } + if ( fRegs ) + { + pFrames->nRegs = pAig->nRegs; + Aig_ManForEachLiSeq( pAig, pObj, i ) + { + pObjNew = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,fEnlarge?0:nFs-1) ); + Aig_ObjSetFrames( pObjMap, nFs, pObj, nFs-1, pObjNew ); + } + } + Aig_ManCleanup( pFrames ); + // return the new manager + if ( ppObjMap ) + *ppObjMap = pObjMap; + else + free( pObjMap ); + return pFrames; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/aig/aigHaig.c b/src/abc8/aig/aigHaig.c new file mode 100644 index 00000000..eaf9fd05 --- /dev/null +++ b/src/abc8/aig/aigHaig.c @@ -0,0 +1,270 @@ +/**CFile**************************************************************** + + FileName [aigHaig.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: aigHaig.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "satSolver.h" +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Aig_HaigObjFrames( Aig_Obj_t ** ppMap, int nFrames, Aig_Obj_t * pObj, int f ) { return ppMap[nFrames*pObj->Id + f]; } +static inline void Aig_HaigObjSetFrames( Aig_Obj_t ** ppMap, int nFrames, Aig_Obj_t * pObj, int f, Aig_Obj_t * pNode ) { ppMap[nFrames*pObj->Id + f] = pNode; } +static inline Aig_Obj_t * Aig_HaigObjChild0Frames( Aig_Obj_t ** ppMap, int nFrames, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_HaigObjFrames(ppMap,nFrames,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Aig_HaigObjChild1Frames( Aig_Obj_t ** ppMap, int nFrames, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_HaigObjFrames(ppMap,nFrames,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs speculative reduction for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ManHaigFramesNode( Aig_Obj_t ** ppMap, int nFrames, Aig_Man_t * pFrames, Aig_Obj_t * pObj, int iFrame ) +{ + Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter; + // skip nodes without representative + pObjRepr = pObj->pHaig; + if ( pObjRepr == NULL ) + return; + assert( !Aig_IsComplement(pObjRepr) ); + assert( pObjRepr->Id < pObj->Id ); + // get the new node + pObjNew = Aig_HaigObjFrames( ppMap, nFrames, pObj, iFrame ); + // get the new node of the representative + pObjReprNew = Aig_HaigObjFrames( ppMap, nFrames, 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 + Aig_HaigObjSetFrames( ppMap, nFrames, pObj, iFrame, pObjNew2 ); + // add the constraint + pMiter = Aig_Exor( pFrames, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) ); + pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); + pMiter = Aig_Not( pMiter ); + Aig_ObjCreatePo( pFrames, pMiter ); +} + +/**Function************************************************************* + + Synopsis [Prepares the inductive case with speculative reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManHaigFrames( Aig_Man_t * pHaig, int nFrames ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + Aig_Obj_t ** ppMap; + int i, k, f; + assert( nFrames >= 2 ); + assert( Aig_ManRegNum(pHaig) > 0 ); + assert( Aig_ManRegNum(pHaig) < Aig_ManPiNum(pHaig) ); + + // create node mapping + ppMap = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pHaig) * nFrames ); + memset( ppMap, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pHaig) * nFrames ); + + // start the frames + pFrames = Aig_ManStart( Aig_ManObjNumMax(pHaig) * nFrames ); + pFrames->pName = Aig_UtilStrsav( pHaig->pName ); + pFrames->nRegs = pHaig->nRegs; + + // create PI nodes for the frames + for ( f = 0; f < nFrames; f++ ) + Aig_HaigObjSetFrames( ppMap, nFrames, Aig_ManConst1(pHaig), f, Aig_ManConst1(pFrames) ); + for ( f = 0; f < nFrames; f++ ) + Aig_ManForEachPiSeq( pHaig, pObj, i ) + Aig_HaigObjSetFrames( ppMap, nFrames, pObj, f, Aig_ObjCreatePi(pFrames) ); + // create latches for the first frame + Aig_ManForEachLoSeq( pHaig, pObj, i ) + Aig_HaigObjSetFrames( ppMap, nFrames, pObj, 0, Aig_ObjCreatePi(pFrames) ); + + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // mark the asserts + if ( f == nFrames - 1 ) + pFrames->nAsserts = Aig_ManPoNum(pFrames); + // constrain latch outputs and internal nodes + Aig_ManForEachObj( pHaig, pObj, i ) + { + if ( Aig_ObjIsPi(pObj) && Aig_HaigObjFrames(ppMap, nFrames, pObj, f) == NULL ) + { + Aig_ManHaigFramesNode( ppMap, nFrames, pFrames, pObj, f ); + } + else if ( Aig_ObjIsNode(pObj) ) + { + pObjNew = Aig_And( pFrames, + Aig_HaigObjChild0Frames(ppMap,nFrames,pObj,f), + Aig_HaigObjChild1Frames(ppMap,nFrames,pObj,f) ); + Aig_HaigObjSetFrames( ppMap, nFrames, pObj, f, pObjNew ); + Aig_ManHaigFramesNode( ppMap, nFrames, pFrames, pObj, f ); + } + } + +/* + // set the constraints on the latch outputs + Aig_ManForEachLoSeq( pHaig, pObj, i ) + Aig_ManHaigFramesNode( ppMap, nFrames, pFrames, pObj, f ); + // add internal nodes of this frame + Aig_ManForEachNode( pHaig, pObj, i ) + { + pObjNew = Aig_And( pFrames, + Aig_HaigObjChild0Frames(ppMap,nFrames,pObj,f), + Aig_HaigObjChild1Frames(ppMap,nFrames,pObj,f) ); + Aig_HaigObjSetFrames( ppMap, nFrames, pObj, f, pObjNew ); + Aig_ManHaigFramesNode( ppMap, nFrames, pFrames, pObj, f ); + } +*/ + // transfer latch inputs to the latch outputs + Aig_ManForEachLiLoSeq( pHaig, pObjLi, pObjLo, k ) + { + pObjNew = Aig_HaigObjChild0Frames(ppMap,nFrames,pObjLi,f); + Aig_HaigObjSetFrames( ppMap, nFrames, pObjLo, f+1, pObjNew ); + } + } + + // remove dangling nodes + Aig_ManCleanup( pFrames ); + free( ppMap ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManHaigVerify( Aig_Man_t * pHaig ) +{ + int nBTLimit = 0; + Aig_Man_t * pFrames; + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Aig_Obj_t * pObj; + int i, Lit, RetValue, Counter; + int clk = clock(); + + // create time frames with speculative reduction and convert them into CNF +clk = clock(); + pFrames = Aig_ManHaigFrames( pHaig, 2 ); + pCnf = Cnf_DeriveSimple( pFrames, Aig_ManPoNum(pFrames) - pFrames->nAsserts ); +// pCnf = Cnf_Derive( pFrames, Aig_ManPoNum(pFrames) - pFrames->nAsserts ); +//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 ); + // create the SAT solver to be used for this problem + pSat = Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + + printf( "HAIG regs = %d. HAIG nodes = %d. Outputs = %d.\n", + Aig_ManRegNum(pHaig), Aig_ManNodeNum(pHaig), Aig_ManPoNum(pHaig) ); + printf( "Frames regs = %d. Frames nodes = %d. Outputs = %d. Assumptions = %d. Asserts = %d.\n", + Aig_ManRegNum(pFrames), Aig_ManNodeNum(pFrames), Aig_ManPoNum(pFrames), + pFrames->nAsserts, Aig_ManPoNum(pFrames) - pFrames->nAsserts ); + +PRT( "Preparation", clock() - clk ); + if ( pSat == NULL ) + { + printf( "Aig_ManHaigVerify(): Computed CNF is not valid.\n" ); + return -1; + } + + // solve each output +clk = clock(); + Counter = 0; + Aig_ManForEachPo( pFrames, pObj, i ) + { + if ( i < pFrames->nAsserts ) + continue; + Lit = toLitCond( pCnf->pVarNums[pObj->Id], pObj->fPhase ); + RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + if ( RetValue != l_False ) + Counter++; + } +PRT( "Solving ", clock() - clk ); + if ( Counter ) + printf( "Verification failed for %d classes.\n", Counter ); + else + printf( "Verification is successful.\n" ); + + // clean up + Aig_ManStop( pFrames ); + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManHaigRecord( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // start the HAIG + p->pManHaig = Aig_ManDup( p, 1 ); + // set the pointers to the HAIG nodes + Aig_ManForEachObj( p, pObj, i ) + pObj->pHaig = pObj->pData; + // remove structural hashing table + Aig_TableClear( p->pManHaig ); + // perform a sequence of synthesis steps + pNew = Aig_ManRetimeFrontier( p, 10000 ); + // use the haig for verification + Aig_ManDumpBlif( pNew->pManHaig, "haig_temp.blif" ); + Aig_ManHaigVerify( pNew->pManHaig ); + Aig_ManStop( pNew ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/aig/aigInter.c b/src/abc8/aig/aigInter.c new file mode 100644 index 00000000..b3bc28b2 --- /dev/null +++ b/src/abc8/aig/aigInter.c @@ -0,0 +1,174 @@ +/**CFile**************************************************************** + + FileName [aigInter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Interpolate two AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigInter.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "cnf.h" +#include "satStore.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose ) +{ + void * pSatCnf = NULL; + Inta_Man_t * pManInter; + Aig_Man_t * pRes; + sat_solver * pSat; + Cnf_Dat_t * pCnfOn, * pCnfOff; + Vec_Int_t * vVarsAB; + Aig_Obj_t * pObj, * pObj2; + int Lits[3], status, i; + int clk = clock(); + + assert( Aig_ManPiNum(pManOn) == Aig_ManPiNum(pManOff) ); + + // derive CNFs + pCnfOn = Cnf_Derive( pManOn, 0 ); + pCnfOff = Cnf_Derive( pManOff, 0 ); +// pCnfOn = Cnf_DeriveSimple( pManOn, 0 ); +// pCnfOff = Cnf_DeriveSimple( pManOff, 0 ); + Cnf_DataLift( pCnfOff, pCnfOn->nVars ); + + // start the solver + pSat = sat_solver_new(); + sat_solver_store_alloc( pSat ); + sat_solver_setnvars( pSat, pCnfOn->nVars + pCnfOff->nVars ); + + // add clauses of A + for ( i = 0; i < pCnfOn->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfOn->pClauses[i], pCnfOn->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); + return NULL; + } + } + sat_solver_store_mark_clauses_a( pSat ); + + // add clauses of B + for ( i = 0; i < pCnfOff->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfOff->pClauses[i], pCnfOff->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); + return NULL; + } + } + + // add PI clauses + // collect the common variables + vVarsAB = Vec_IntAlloc( Aig_ManPiNum(pManOn) ); + Aig_ManForEachPi( pManOn, pObj, i ) + { + Vec_IntPush( vVarsAB, pCnfOn->pVarNums[pObj->Id] ); + pObj2 = Aig_ManPi( pManOff, i ); + + Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_store_mark_roots( pSat ); + if ( fVerbose ) + { + PRT( "Prepare", clock() - clk ); + } + +/* + status = sat_solver_simplify(pSat); + if ( status == 0 ) + { + Vec_IntFree( vVarsAB ); + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); + return NULL; + } +*/ + + // solve the problem + clk = clock(); + status = sat_solver_solve( pSat, NULL, NULL, (sint64)0, (sint64)0, (sint64)0, (sint64)0 ); + if ( fVerbose ) + { + PRT( "Solving", clock() - clk ); + } + if ( status == l_False ) + { + pSatCnf = sat_solver_store_release( pSat ); +// printf( "unsat\n" ); + } + else if ( status == l_True ) + { +// printf( "sat\n" ); + } + else + { +// printf( "undef\n" ); + } + sat_solver_delete( pSat ); + if ( pSatCnf == NULL ) + { + printf( "The SAT problem is not unsat.\n" ); + Vec_IntFree( vVarsAB ); + return NULL; + } + + // create the resulting manager + pManInter = Inta_ManAlloc(); + pRes = Inta_ManInterpolate( pManInter, pSatCnf, vVarsAB, fVerbose ); + Inta_ManFree( pManInter ); + + Vec_IntFree( vVarsAB ); + Sto_ManFree( pSatCnf ); + return pRes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/aig/aigMan.c b/src/abc8/aig/aigMan.c new file mode 100644 index 00000000..da6fb9ba --- /dev/null +++ b/src/abc8/aig/aigMan.c @@ -0,0 +1,369 @@ +/**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" +//#include "tim.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) ); + if ( pNew->pManHaig == NULL ) + return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + else + { + Aig_Obj_t * pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_Regular(pObjNew->pHaig)->pHaig = Aig_Regular(pObj->pHaig); + return pObj->pData = pObjNew; + } +} + +/**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, * pObjNew; + 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; + pNew->pManHaig = p->pManHaig; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManConst1(pNew)->pHaig = Aig_ManConst1(p)->pHaig; + Aig_ManForEachPi( p, pObj, i ) + { + pObjNew = Aig_ObjCreatePi( pNew ); + pObjNew->pHaig = pObj->pHaig; + pObjNew->Level = pObj->Level; + pObj->pData = pObjNew; + } + // duplicate internal nodes + if ( fOrdered ) + { + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + { + if ( pNew->pManHaig == NULL ) + pObj->pData = Aig_ObjChild0Copy(pObj); + else + { + Aig_Obj_t * pObjNew = Aig_ObjChild0Copy(pObj); + Aig_Regular(pObjNew->pHaig)->pHaig = Aig_Regular(pObj->pHaig); + pObj->pData = pObjNew; + } + } + else if ( Aig_ObjIsNode(pObj) ) + { + if ( pNew->pManHaig == NULL ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + else + { + Aig_Obj_t * pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_Regular(pObjNew->pHaig)->pHaig = Aig_Regular(pObj->pHaig); + pObj->pData = pObjNew; + } + } + } + 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 ) + { + pObjNew = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + pObjNew->pHaig = pObj->pHaig; + pObj->pData = pObjNew; + } + assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + // pass the HAIG to the new AIG + p->pManHaig = NULL; + Aig_ManForEachObj( p, pObj, i ) + pObj->pHaig = NULL; + // 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->pManHaig ) + Aig_ManStop( p->pManHaig ); + 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 ) +// Tim_ManStop( 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->pSeqModel ); + 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/src/abc8/aig/aigMem.c b/src/abc8/aig/aigMem.c new file mode 100644 index 00000000..dab90777 --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigMffc.c b/src/abc8/aig/aigMffc.c new file mode 100644 index 00000000..47ce896d --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigObj.c b/src/abc8/aig/aigObj.c new file mode 100644 index 00000000..80838e19 --- /dev/null +++ b/src/abc8/aig/aigObj.c @@ -0,0 +1,431 @@ +/**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 ); + if ( p->pManHaig ) + { + pGhost->pFanin0 = Aig_ObjHaig( pGhost->pFanin0 ); + pGhost->pFanin1 = Aig_ObjHaig( pGhost->pFanin1 ); + pObj->pHaig = Aig_ObjCreate( p->pManHaig, pGhost ); + } + 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) ); + // map the HAIG nodes + if ( p->pManHaig != NULL ) + { + assert( pObjNewR->pHaig != NULL ); + assert( pObjNewR->pHaig->pHaig == NULL ); + pObjNewR->pHaig->pHaig = pObjOld->pHaig; + } + // 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 ); + // update the haig node + pObjOld->pHaig = pObjNew->pHaig; + // 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/abc8/aig/aigOper.c b/src/abc8/aig/aigOper.c new file mode 100644 index 00000000..c19f551e --- /dev/null +++ b/src/abc8/aig/aigOper.c @@ -0,0 +1,541 @@ +/**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; + if ( p->pTable == NULL ) + { +// pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND ); + pGhost = Aig_ManGhost(p); + pGhost->Type = AIG_OBJ_AND; + pGhost->pFanin0 = p0; + pGhost->pFanin1 = p1; + return Aig_ObjCreate( p, pGhost ); + } + // 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/abc8/aig/aigOrder.c b/src/abc8/aig/aigOrder.c new file mode 100644 index 00000000..62aeca6e --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigPart.c b/src/abc8/aig/aigPart.c new file mode 100644 index 00000000..de13653c --- /dev/null +++ b/src/abc8/aig/aigPart.c @@ -0,0 +1,992 @@ +/**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 partition and its 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, int fVerbose ) +{ +// 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 + if ( fVerbose ) + 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 ); + } + if ( fVerbose ) + 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/abc8/aig/aigRepr.c b/src/abc8/aig/aigRepr.c new file mode 100644 index 00000000..5ee6c9af --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigRet.c b/src/abc8/aig/aigRet.c new file mode 100644 index 00000000..d1784b1b --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigRetF.c b/src/abc8/aig/aigRetF.c new file mode 100644 index 00000000..8ca4fba1 --- /dev/null +++ b/src/abc8/aig/aigRetF.c @@ -0,0 +1,219 @@ +/**CFile**************************************************************** + + FileName [aigRetF.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Retiming frontier.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigRetF.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Mark the nodes reachable from the PIs in the reverse order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManRetimeMark_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB ) + return 1; + if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) + return 0; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return pObj->fMarkB; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ManRetimeMark_rec( p, Aig_ObjFanin0(pObj) ) ) + return pObj->fMarkB = 1; + if ( Aig_ObjIsNode(pObj) && Aig_ManRetimeMark_rec( p, Aig_ObjFanin1(pObj) ) ) + return pObj->fMarkB = 1; + assert( pObj->fMarkB == 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Mark the nodes reachable from the true PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManRetimeMark( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int fChange, i; + // mark the PIs + Aig_ManForEachObj( p, pObj, i ) + assert( pObj->fMarkB == 0 ); + Aig_ManForEachPiSeq( p, pObj, i ) + pObj->fMarkB = 1; + // map registers into each other + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + assert( pObjLo->pNext == NULL ); + assert( pObjLi->pNext == NULL ); + pObjLo->pNext = pObjLi; + pObjLi->pNext = pObjLo; + } + // iterativively mark the logic reachable from PIs + fChange = 1; + while ( fChange ) + { + fChange = 0; + Aig_ManIncrementTravId( p ); + Aig_ManForEachPo( p, pObj, i ) + { + if ( pObj->fMarkB ) + continue; + if ( Aig_ManRetimeMark_rec( p, pObj ) ) + { + if ( pObj->pNext ) + pObj->pNext->fMarkB = 1; + fChange = 1; + } + } + } + // clean register mapping + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + pObjLo->pNext = pObjLi->pNext = NULL; +} + + +/**Function************************************************************* + + Synopsis [Performs forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax ) +{ + Aig_Obj_t * pObj, * pObjNew, * pObjLo, * pObjLo0, * pObjLo1, * pObjLi, * pObjLi0, * pObjLi1;//, * pObjLi0_, * pObjLi1_, * pObjLi0__, * pObjLi1__; + int i, Counter, fCompl, fChange; + assert( Aig_ManRegNum(p) > 0 ); + // remove structural hashing table + Aig_TableClear( p ); + // mark the retimable nodes + Aig_ManRetimeMark( p ); + // mark the register outputs + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + pObjLo->fMarkA = 1; + pObjLo->pNext = pObjLi; + pObjLi->pNext = pObjLo; + } + // go through the nodes and find retimable ones + Counter = 0; + fChange = 1; + while ( fChange ) + { + fChange = 0; + Aig_ManForEachNode( p, pObj, i ) + { + if ( !pObj->fMarkB ) + continue; + if ( Aig_ObjIsBuf(pObj) ) + continue; + // get the real inputs of the node (skipping the buffers) + pObjLo0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pObjLo1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); + if ( !Aig_Regular(pObjLo0)->fMarkA || !Aig_Regular(pObjLo1)->fMarkA ) + continue; + // remember complemented attribute + fCompl = Aig_IsComplement(pObjLo0) & Aig_IsComplement(pObjLo1); + // get the register inputs +// pObjLi0_ = Aig_Regular(pObjLo0)->pNext; +// pObjLi1_ = Aig_Regular(pObjLo1)->pNext; +// pObjLi0__ = Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext); +// pObjLi1__ = Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext); + pObjLi0 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext), Aig_IsComplement(pObjLo0) ); + pObjLi1 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext), Aig_IsComplement(pObjLo1) ); + // create new node + pObjNew = Aig_And( p, pObjLi0, pObjLi1 ); + pObjNew->fMarkB = 1; + // create new register + pObjLo = Aig_ObjCreatePi(p); + pObjLo->fMarkA = 1; + pObjLi = Aig_ObjCreatePo( p, Aig_NotCond(pObjNew, fCompl) ); + p->nRegs++; + pObjLo->pNext = pObjLi; + pObjLi->pNext = pObjLo; + // add the buffer + Aig_ObjDisconnect( p, pObj ); + pObj->Type = AIG_OBJ_BUF; + p->nObjs[AIG_OBJ_AND]--; + p->nObjs[AIG_OBJ_BUF]++; + Aig_ObjConnect( p, pObj, Aig_NotCond(pObjLo, fCompl), NULL ); + // create HAIG if defined + if ( p->pManHaig ) + { + // create HAIG latch + pObjLo->pHaig = Aig_ObjCreatePi( p->pManHaig ); + pObjLi->pHaig = Aig_ObjCreatePo( p->pManHaig, Aig_ObjHaig( Aig_ObjChild0(pObjLi) ) ); + // create equivalence class + assert( pObjLo->pHaig != NULL ); + assert( pObjLo->pHaig->pHaig == NULL ); + pObjLo->pHaig->pHaig = Aig_Regular(pObj->pHaig); + } + // mark the change + fChange = 1; + // check the limit + if ( ++Counter >= nStepsMax ) + { + fChange = 0; + break; + } + } + } + // clean the markings + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + pObjLo->fMarkA = 0; + pObjLo->pNext = pObjLi->pNext = NULL; + } + Aig_ManForEachObj( p, pObj, i ) + pObj->fMarkB = 0; + // remove useless registers + Aig_ManSeqCleanup( p ); + // rehash the nodes + return Aig_ManDup( p, 1 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/aig/aigScl.c b/src/abc8/aig/aigScl.c new file mode 100644 index 00000000..9721dd17 --- /dev/null +++ b/src/abc8/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 node 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_ObjIsBuf(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/src/abc8/aig/aigSeq.c b/src/abc8/aig/aigSeq.c new file mode 100644 index 00000000..daafeab1 --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigShow.c b/src/abc8/aig/aigShow.c new file mode 100644 index 00000000..96b0e37f --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigTable.c b/src/abc8/aig/aigTable.c new file mode 100644 index 00000000..357b63c3 --- /dev/null +++ b/src/abc8/aig/aigTable.c @@ -0,0 +1,289 @@ +/**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; + if ( p->pTable == NULL ) + return; + 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; + if ( p->pTable == NULL ) + return; + 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 ); + } +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Aig_TableClear( Aig_Man_t * p ) +{ + FREE( p->pTable ); + p->nTableSize = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/aig/aigTiming.c b/src/abc8/aig/aigTiming.c new file mode 100644 index 00000000..de8fdc7c --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigTruth.c b/src/abc8/aig/aigTruth.c new file mode 100644 index 00000000..a92f9e1d --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigTsim.c b/src/abc8/aig/aigTsim.c new file mode 100644 index 00000000..a8a3dda8 --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aigUtil.c b/src/abc8/aig/aigUtil.c new file mode 100644 index 00000000..f6f34de9 --- /dev/null +++ b/src/abc8/aig/aigUtil.c @@ -0,0 +1,855 @@ +/**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 a 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; + } + // check if constant is used + Aig_ManForEachPo( p, pObj, i ) + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + pConst1 = Aig_ManConst1(p); + // 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 + if ( pConst1 ) + fprintf( pFile, ".names n%0*d\n 1\n", nDigits, pConst1->iData ); + 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) ); + } + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG into a Verilog 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; + } + // check if constant is used + Aig_ManForEachPo( p, pObj, i ) + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + pConst1 = Aig_ManConst1(p); + // 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 ); + if ( pConst1 ) + fprintf( pFile, "wire n%0*d;\n", nDigits, pConst1->iData ); + // write nodes + if ( pConst1 ) + fprintf( pFile, "assign n%0*d = 1\'b1;\n", nDigits, pConst1->iData ); + 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_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 ); + } + } + + // 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/abc8/aig/aigWin.c b/src/abc8/aig/aigWin.c new file mode 100644 index 00000000..0485b243 --- /dev/null +++ b/src/abc8/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/src/abc8/aig/aig_.c b/src/abc8/aig/aig_.c new file mode 100644 index 00000000..b2313d35 --- /dev/null +++ b/src/abc8/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/src/abc8/aig/module.make b/src/abc8/aig/module.make new file mode 100644 index 00000000..4b81834f --- /dev/null +++ b/src/abc8/aig/module.make @@ -0,0 +1,23 @@ +SRC += src/aig/aig/aigCheck.c \ + src/aig/aig/aigDfs.c \ + src/aig/aig/aigFanout.c \ + src/aig/aig/aigFrames.c \ + src/aig/aig/aigHaig.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/aigRetF.c \ + src/aig/aig/aigScl.c \ + src/aig/aig/aigSeq.c \ + src/aig/aig/aigTable.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/abc8/bsat/module.make b/src/abc8/bsat/module.make new file mode 100644 index 00000000..563c8dfc --- /dev/null +++ b/src/abc8/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/src/abc8/bsat/satInter.c b/src/abc8/bsat/satInter.c new file mode 100644 index 00000000..8e07e9f6 --- /dev/null +++ b/src/abc8/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_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/abc8/bsat/satInterA.c b/src/abc8/bsat/satInterA.c new file mode 100644 index 00000000..513a9044 --- /dev/null +++ b/src/abc8/bsat/satInterA.c @@ -0,0 +1,970 @@ +/**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" +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// variable assignments +static const lit LIT_UNDEF = 0xffffffff; + +// interpolation manager +struct Inta_Man_t_ +{ + // clauses of the problems + Sto_Man_t * pCnf; // the set of CNF clauses for A and B + Vec_Int_t * vVarsAB; // the array of global variables + // 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 + Aig_Man_t * pAig; // the AIG manager for recording the interpolant + int * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] + Aig_Obj_t ** pInters; // storage for interpolants as truth tables (size nClauses) + int nIntersAlloc; // the allocated size of truth table array + // 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 Aig_Obj_t ** Inta_ManAigRead( Inta_Man_t * pMan, Sto_Cls_t * pCls ) { return pMan->pInters + pCls->Id; } +static inline void Inta_ManAigClear( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst0(pMan->pAig); } +static inline void Inta_ManAigFill( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst1(pMan->pAig); } +static inline void Inta_ManAigCopy( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = *q; } +static inline void Inta_ManAigAnd( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_And(pMan->pAig, *p, *q); } +static inline void Inta_ManAigOr( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, *q); } +static inline void Inta_ManAigOrNot( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(*q)); } +static inline void Inta_ManAigOrVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_IthVar(pMan->pAig, v)); } +static inline void Inta_ManAigOrNotVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(Aig_IthVar(pMan->pAig, v))); } + +// reading/writing the proof for a clause +static inline int Inta_ManProofGet( Inta_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } +static inline void Inta_ManProofSet( Inta_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Inta_Man_t * Inta_ManAlloc() +{ + Inta_Man_t * p; + // allocate the manager + p = (Inta_Man_t *)malloc( sizeof(Inta_Man_t) ); + memset( p, 0, sizeof(Inta_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 Inta_ManGlobalVars( Inta_Man_t * p ) +{ + Sto_Cls_t * pClause; + int LargeNum = -100000000; + 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] = LargeNum; + } + } + } + assert( nVarsAB <= Vec_IntSize(p->vVarsAB) ); + + // order global variables + nVarsAB = 0; + Vec_IntForEachEntry( p->vVarsAB, Var, v ) + p->pVarTypes[Var] = -(1+nVarsAB++); + + // check that there is no extra global variables + for ( v = 0; v < p->pCnf->nVars; v++ ) + assert( p->pVarTypes[v] != LargeNum ); + return nVarsAB; +} + +/**Function************************************************************* + + Synopsis [Resize proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManResize( Inta_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 = (int *) realloc( p->pVarTypes, sizeof(int) * 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(int) * 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 + Inta_ManGlobalVars( p ); + + // 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->pCnf->nClauses ) + { + p->nIntersAlloc = p->pCnf->nClauses; + p->pInters = (Aig_Obj_t **) realloc( p->pInters, sizeof(Aig_Obj_t *) * p->nIntersAlloc ); + } + memset( p->pInters, 0, sizeof(Aig_Obj_t *) * p->pCnf->nClauses ); +} + +/**Function************************************************************* + + Synopsis [Deallocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManFree( Inta_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 Inta_ManPrintClause( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + int i; + printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Inta_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 Inta_ManPrintResolvent( lit * pResLits, int nResLits ) +{ + int i; + printf( "Resolvent: {" ); + for ( i = 0; i < nResLits; i++ ) + printf( " %d", pResLits[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the interpolant for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrintInterOne( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + printf( "Clause %2d : ", pClause->Id ); +// Extra_PrintBinary___( stdout, Inta_ManAigRead(p, pClause), (1 << p->nVarsAB) ); + printf( "\n" ); +} + + + +/**Function************************************************************* + + Synopsis [Adds one clause to the watcher list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Inta_ManWatchClause( Inta_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 Inta_ManEnqueue( Inta_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 Inta_ManCancelUntil( Inta_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 * Inta_ManPropagateOne( Inta_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]) + Inta_ManWatchClause( p, pCur, pCur->pLits[1] ); + break; + } + if ( i < (int)pCur->nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + if ( Inta_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 * Inta_ManPropagate( Inta_Man_t * p, int Start ) +{ + Sto_Cls_t * pClause; + int i; + int clk = clock(); + for ( i = Start; i < p->nTrailSize; i++ ) + { + pClause = Inta_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 Inta_ManProofWriteOne( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + Inta_ManProofSet( p, pClause, ++p->Counter ); + + if ( p->fProofWrite ) + { + int v; + fprintf( p->pFile, "%d", Inta_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 Inta_ManProofTraceOne( Inta_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 ) + Inta_ManAigCopy( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pConflict) ); + + // follow the trail backwards + PrevId = Inta_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( Inta_ManProofGet(p, pReason) > 0 ); + p->Counter++; + if ( p->fProofWrite ) + fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Inta_ManProofGet(p, pReason) ); + PrevId = p->Counter; + + if ( p->pCnf->nClausesA ) + { + if ( p->pVarTypes[Var] == 1 ) // var of A + Inta_ManAigOr( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); + else + Inta_ManAigAnd( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); + } + + // resolve the temporary resolvent with the reason clause + if ( p->fProofVerif ) + { + int v1, v2; + if ( fPrint ) + Inta_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 ) + Inta_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 ); + Inta_ManPrintClause( p, pConflict ); + Inta_ManPrintResolvent( p->pResLits, p->nResLits ); + Inta_ManPrintClause( p, pFinal ); + } + } +p->timeTrace += clock() - clk; + + // return the proof pointer + if ( p->pCnf->nClausesA ) + { +// Inta_ManPrintInterOne( p, pFinal ); + } + Inta_ManProofSet( p, pFinal, p->Counter ); + return p->Counter; +} + +/**Function************************************************************* + + Synopsis [Records the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManProofRecordOne( Inta_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 ( !Inta_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumptions + pConflict = Inta_ManPropagate( p, p->nRootSize ); + if ( pConflict == NULL ) + { + assert( 0 ); // cannot prove + return 0; + } + + // construct the proof + Inta_ManProofTraceOne( p, pConflict, pClause ); + + // undo to the root level + Inta_ManCancelUntil( p, p->nRootSize ); + + // add large clauses to the watched lists + if ( pClause->nLits > 1 ) + { + Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); + Inta_ManWatchClause( p, pClause, pClause->pLits[1] ); + return 1; + } + assert( pClause->nLits == 1 ); + + // if the clause proved is unit, add it and propagate + if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumption + pConflict = Inta_ManPropagate( p, p->nRootSize ); + if ( pConflict ) + { + // construct the proof + Inta_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 Inta_ManProcessRoots( Inta_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 ) + { + Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); + Inta_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 ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + // detected root level conflict + printf( "Error in Inta_ManProcessRoots(): Detected a root-level conflict too early!\n" ); + assert( 0 ); + return 0; + } + } + + // propagate the root unit clauses + pClause = Inta_ManPropagate( p, 0 ); + if ( pClause ) + { + // detected root level conflict + Inta_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 Inta_ManPrepareInter( Inta_Man_t * p ) +{ + Sto_Cls_t * pClause; + int Var, VarAB, v; + + // set interpolants for root clauses + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( !pClause->fA ) // clause of B + { + Inta_ManAigFill( p, Inta_ManAigRead(p, pClause) ); +// Inta_ManPrintInterOne( p, pClause ); + continue; + } + // clause of A + Inta_ManAigClear( p, Inta_ManAigRead(p, pClause) ); + 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 < Vec_IntSize(p->vVarsAB) ); + if ( lit_sign(pClause->pLits[v]) ) // negative var + Inta_ManAigOrNotVar( p, Inta_ManAigRead(p, pClause), VarAB ); + else + Inta_ManAigOrVar( p, Inta_ManAigRead(p, pClause), VarAB ); + } + } +// Inta_ManPrintInterOne( p, pClause ); + } +} + +/**Function************************************************************* + + Synopsis [Computes interpolant for the given CNF.] + + Description [Takes the interpolation manager, the CNF deriving by the SAT + solver, which includes ClausesA, ClausesB, and learned clauses. Additional + arguments are the vector of variables common to AB and the verbosiness flag. + Returns the AIG manager with a single output, containing the interpolant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose ) +{ + Aig_Man_t * pRes; + 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; + p->vVarsAB = vVarsAB; + p->pAig = pRes = Aig_ManStart( 10000 ); + Aig_IthVar( p->pAig, Vec_IntSize(p->vVarsAB) - 1 ); + + // adjust the manager + Inta_ManResize( p ); + + // prepare the interpolant computation + Inta_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 ) + Inta_ManProofWriteOne( p, pClause ); + + // propagate root level assignments + if ( Inta_ManProcessRoots( p ) ) + { + // if there is no conflict, consider learned clauses + Sto_ManForEachClause( p->pCnf, pClause ) + { + if ( pClause->fRoot ) + continue; + if ( !Inta_ManProofRecordOne( p, pClause ) ) + { + RetValue = 0; + break; + } + } + } + + // stop the proof + if ( p->fProofWrite ) + { + fclose( p->pFile ); + p->pFile = NULL; + } + + if ( fVerbose ) + { + PRT( "Interpo", clock() - clkTotal ); + 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; + } + + Aig_ObjCreatePo( pRes, *Inta_ManAigRead( p, p->pCnf->pTail ) ); + Aig_ManCleanup( pRes ); + + p->pAig = NULL; + return pRes; + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/bsat/satMem.c b/src/abc8/bsat/satMem.c new file mode 100644 index 00000000..7fa1a824 --- /dev/null +++ b/src/abc8/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 "vec.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/abc8/bsat/satMem.h b/src/abc8/bsat/satMem.h new file mode 100644 index 00000000..22b7a87c --- /dev/null +++ b/src/abc8/bsat/satMem.h @@ -0,0 +1,80 @@ +/**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 +#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/abc8/bsat/satSolver.c b/src/abc8/bsat/satSolver.c new file mode 100644 index 00000000..fbc9874d --- /dev/null +++ b/src/abc8/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 long)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/abc8/bsat/satSolver.h b/src/abc8/bsat/satSolver.h new file mode 100644 index 00000000..c1bf32a7 --- /dev/null +++ b/src/abc8/bsat/satSolver.h @@ -0,0 +1,210 @@ +/************************************************************************************************** +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)); } +static inline int lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n; } + + +//================================================================================================= +// 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; +}; + +static int sat_solver_var_value( sat_solver* s, int v ) +{ + assert( s->model.ptr != NULL && v < s->size ); + return (int)(s->model.ptr[v] == l_True); +} +static int sat_solver_var_literal( sat_solver* s, int v ) +{ + assert( s->model.ptr != NULL && v < s->size ); + return toLitCond( v, s->model.ptr[v] != l_True ); +} +static void sat_solver_act_var_clear(sat_solver* s) +{ + int i; + for (i = 0; i < s->size; i++) + s->activity[i] = 0.0; + s->var_inc = 1.0; +} + +#endif diff --git a/src/abc8/bsat/satStore.c b/src/abc8/bsat/satStore.c new file mode 100644 index 00000000..f968162e --- /dev/null +++ b/src/abc8/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/src/abc8/bsat/satStore.h b/src/abc8/bsat/satStore.h new file mode 100644 index 00000000..b66abc8f --- /dev/null +++ b/src/abc8/bsat/satStore.h @@ -0,0 +1,146 @@ +/**CFile**************************************************************** + + FileName [satStore.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 __SAT_STORE_H__ +#define __SAT_STORE_H__ + +#include "satSolver.h" + +/* + The trace of SAT solving contains the original clauses 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; +// 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; } +*/ + +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 +}; + +// 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(); +extern void Int_ManFree( Int_Man_t * p ); +extern int Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult ); + +/*=== satInterA.c ==========================================================*/ +typedef struct Inta_Man_t_ Inta_Man_t; +extern Inta_Man_t * Inta_ManAlloc(); +extern void Inta_ManFree( Inta_Man_t * p ); +extern void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/abc8/bsat/satTrace.c b/src/abc8/bsat/satTrace.c new file mode 100644 index 00000000..111e8dfb --- /dev/null +++ b/src/abc8/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/src/abc8/bsat/satUtil.c b/src/abc8/bsat/satUtil.c new file mode 100644 index 00000000..3961cf7e --- /dev/null +++ b/src/abc8/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 "vec.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/abc8/bsat/satVec.h b/src/abc8/bsat/satVec.h new file mode 100644 index 00000000..d7fce5c0 --- /dev/null +++ b/src/abc8/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/src/abc8/cnf/cnf.h b/src/abc8/cnf/cnf.h new file mode 100644 index 00000000..5f31ef37 --- /dev/null +++ b/src/abc8/cnf/cnf.h @@ -0,0 +1,163 @@ +/**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 "vec2.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_DataLift( Cnf_Dat_t * p, int nVarsPlus ); +extern void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable ); +void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ); +/*=== 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/abc8/cnf/cnfCore.c b/src/abc8/cnf/cnfCore.c new file mode 100644 index 00000000..e1d62de0 --- /dev/null +++ b/src/abc8/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, 0 ); +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/abc8/cnf/cnfCut.c b/src/abc8/cnf/cnfCut.c new file mode 100644 index 00000000..17ab0c78 --- /dev/null +++ b/src/abc8/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/src/abc8/cnf/cnfData.c b/src/abc8/cnf/cnfData.c new file mode 100644 index 00000000..01f6ff8a --- /dev/null +++ b/src/abc8/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[(int)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[(int)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/abc8/cnf/cnfMan.c b/src/abc8/cnf/cnfMan.c new file mode 100644 index 00000000..47bc0b67 --- /dev/null +++ b/src/abc8/cnf/cnfMan.c @@ -0,0 +1,282 @@ +/**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_DataLift( Cnf_Dat_t * p, int nVarsPlus ) +{ + Aig_Obj_t * pObj; + int v; + Aig_ManForEachObj( p->pMan, pObj, v ) + if ( p->pVarNums[pObj->Id] ) + p->pVarNums[pObj->Id] += nVarsPlus; + for ( v = 0; v < p->nLiterals; v++ ) + p->pClauses[0][v] += 2*nVarsPlus; +} + +/**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, int nFrames, int fInit ) +{ + sat_solver * pSat; + int i, f, status; + assert( nFrames > 0 ); + pSat = sat_solver_new(); + sat_solver_setnvars( pSat, p->nVars * nFrames ); + 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; + } + } + if ( nFrames > 1 ) + { + Aig_Obj_t * pObjLo, * pObjLi; + int nLitsAll, * pLits, Lits[2]; + nLitsAll = 2 * p->nVars; + pLits = p->pClauses[0]; + for ( f = 1; f < nFrames; f++ ) + { + // add equality of register inputs/outputs for different timeframes + Aig_ManForEachLiLoSeq( p->pMan, pObjLi, pObjLo, i ) + { + Lits[0] = (f-1)*nLitsAll + toLitCond( p->pVarNums[pObjLi->Id], 0 ); + Lits[1] = f *nLitsAll + toLitCond( p->pVarNums[pObjLo->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + { + sat_solver_delete( pSat ); + return NULL; + } + Lits[0]++; + Lits[1]--; + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + { + sat_solver_delete( pSat ); + return NULL; + } + } + // add clauses for the next timeframe + for ( i = 0; i < p->nLiterals; i++ ) + pLits[i] += nLitsAll; + 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; + } + } + } + // return literals to their original state + nLitsAll = (f-1) * nLitsAll; + for ( i = 0; i < p->nLiterals; i++ ) + pLits[i] -= nLitsAll; + } + if ( fInit ) + { + Aig_Obj_t * pObjLo; + int Lits[1]; + Aig_ManForEachLoSeq( p->pMan, pObjLo, i ) + { + Lits[0] = toLitCond( p->pVarNums[pObjLo->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 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/abc8/cnf/cnfMap.c b/src/abc8/cnf/cnfMap.c new file mode 100644 index 00000000..d966df15 --- /dev/null +++ b/src/abc8/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/src/abc8/cnf/cnfPost.c b/src/abc8/cnf/cnfPost.c new file mode 100644 index 00000000..988275b2 --- /dev/null +++ b/src/abc8/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/src/abc8/cnf/cnfUtil.c b/src/abc8/cnf/cnfUtil.c new file mode 100644 index 00000000..cd47cb58 --- /dev/null +++ b/src/abc8/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/src/abc8/cnf/cnfWrite.c b/src/abc8/cnf/cnfWrite.c new file mode 100644 index 00000000..5a96f23f --- /dev/null +++ b/src/abc8/cnf/cnfWrite.c @@ -0,0 +1,447 @@ +/**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->pMan = p->pManAig; + 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. + New variables will be introduced for these outputs.] + + 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->pMan = p; + 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++; + Aig_ManForEachPo( 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/abc8/cnf/cnf_.c b/src/abc8/cnf/cnf_.c new file mode 100644 index 00000000..7c9ca499 --- /dev/null +++ b/src/abc8/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/src/abc8/cnf/module.make b/src/abc8/cnf/module.make new file mode 100644 index 00000000..dbcaeba4 --- /dev/null +++ b/src/abc8/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/src/abc8/dar/dar.h b/src/abc8/dar/dar.h new file mode 100644 index 00000000..72e7d3d1 --- /dev/null +++ b/src/abc8/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, int fVerbose ); +/*=== 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/abc8/dar/darBalance.c b/src/abc8/dar/darBalance.c new file mode 100644 index 00000000..b3c5d645 --- /dev/null +++ b/src/abc8/dar/darBalance.c @@ -0,0 +1,400 @@ +/**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/abc8/dar/darCore.c b/src/abc8/dar/darCore.c new file mode 100644 index 00000000..141d9b79 --- /dev/null +++ b/src/abc8/dar/darCore.c @@ -0,0 +1,289 @@ +/**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 [Computes the total number of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_ManCutCount( Aig_Man_t * pAig, int * pnCutsK ) +{ + Dar_Cut_t * pCut; + Aig_Obj_t * pObj; + int i, k, nCuts = 0, nCutsK = 0; + Aig_ManForEachNode( pAig, pObj, i ) + Dar_ObjForEachCut( pObj, pCut, k ) + { + nCuts++; + if ( pCut->nLeaves == 4 ) + nCutsK++; + } + if ( pnCutsK ) + *pnCutsK = nCutsK; + return nCuts; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax, int fVerbose ) +{ + Dar_Man_t * p; + Dar_RwrPar_t Pars, * pPars = &Pars; + Aig_Obj_t * pObj; + Aig_MmFixed_t * pMemCuts; + int i, nNodes, clk = 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 ); + // print verbose stats + if ( fVerbose ) + { +// Aig_Obj_t * pObj; + int nCuts, nCutsK;//, i; + nCuts = Dar_ManCutCount( pAig, &nCutsK ); + printf( "Nodes = %6d. Total cuts = %6d. 4-input cuts = %6d.\n", + Aig_ManObjNum(pAig), nCuts, nCutsK ); + printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f Mb ", + sizeof(Dar_Cut_t), 4, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); + PRT( "Runtime", clock() - clk ); +/* + Aig_ManForEachNode( pAig, pObj, i ) + if ( i % 300 == 0 ) + Dar_ObjCutPrint( pAig, 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/abc8/dar/darCut.c b/src/abc8/dar/darCut.c new file mode 100644 index 00000000..79e4dcc4 --- /dev/null +++ b/src/abc8/dar/darCut.c @@ -0,0 +1,739 @@ +/**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 [Prints one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_CutPrint( Dar_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 Dar_ObjCutPrint( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Dar_Cut_t * pCut; + int i; + printf( "Cuts for node %d:\n", pObj->Id ); + Dar_ObjForEachCut( pObj, pCut, i ) + Dar_CutPrint( pCut ); +// printf( "\n" ); +} + +/**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 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/abc8/dar/darData.c b/src/abc8/dar/darData.c new file mode 100644 index 00000000..cb403b8a --- /dev/null +++ b/src/abc8/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/src/abc8/dar/darInt.h b/src/abc8/dar/darInt.h new file mode 100644 index 00000000..dbca5fb2 --- /dev/null +++ b/src/abc8/dar/darInt.h @@ -0,0 +1,166 @@ +/**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 "vec2.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 ); +extern void Dar_ObjCutPrint( Aig_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/abc8/dar/darLib.c b/src/abc8/dar/darLib.c new file mode 100644 index 00000000..e0e97055 --- /dev/null +++ b/src/abc8/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/src/abc8/dar/darMan.c b/src/abc8/dar/darMan.c new file mode 100644 index 00000000..0a5a36b1 --- /dev/null +++ b/src/abc8/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/src/abc8/dar/darPrec.c b/src/abc8/dar/darPrec.c new file mode 100644 index 00000000..8c3a4ce3 --- /dev/null +++ b/src/abc8/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/src/abc8/dar/darRefact.c b/src/abc8/dar/darRefact.c new file mode 100644 index 00000000..fafaf6da --- /dev/null +++ b/src/abc8/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 "kit.h" +#include "darInt.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/src/abc8/dar/darResub.c b/src/abc8/dar/darResub.c new file mode 100644 index 00000000..f819934e --- /dev/null +++ b/src/abc8/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/src/abc8/dar/darScript.c b/src/abc8/dar/darScript.c new file mode 100644 index 00000000..530e913e --- /dev/null +++ b/src/abc8/dar/darScript.c @@ -0,0 +1,393 @@ +/**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( pAig, 0 ); + 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( pAig, 0 ); + 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, 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 ); + + 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, fVerbose ); + 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/src/abc8/dar/dar_.c b/src/abc8/dar/dar_.c new file mode 100644 index 00000000..12fd7d17 --- /dev/null +++ b/src/abc8/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/src/abc8/dar/module.make b/src/abc8/dar/module.make new file mode 100644 index 00000000..b1b0332c --- /dev/null +++ b/src/abc8/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/src/abc8/fra/fra.h b/src/abc8/fra/fra.h new file mode 100644 index 00000000..c024a736 --- /dev/null +++ b/src/abc8/fra/fra.h @@ -0,0 +1,324 @@ +/**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 "vec2.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_Cex_t_ Fra_Cex_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 nMaxLevs; // the maximum number of levels to consider + int fRewrite; // use rewriting for constraint reduction + int fLatchCorr; // computes latch correspondence only + int fUseImps; // use implications + int fWriteImps; // record implications + int fDontShowBar; // does not show progressbar during fraiging +}; + +// 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 +}; + +// simulation manager +struct Fra_Cex_t_ +{ + int iPo; // the zero-based number of PO, for which verification failed + int iFrame; // the zero-based number of the time-frame, for which verificaiton failed + int nRegs; // the number of registers in the miter + int nPis; // the number of primary inputs in the miter + int nBits; // the number of words of bit data used + unsigned pData[0]; // the cex bit data (the number of bits: nRegs + (iFrame+1) * nPis) +}; + +// 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 /// +//////////////////////////////////////////////////////////////////////// + +/*=== fraCec.c ========================================================*/ +extern int Fra_FraigSat( Aig_Man_t * pMan, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ); +extern int Fra_FraigCec( Aig_Man_t ** ppAig, int fVerbose ); +extern int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int fVerbose ); +/*=== 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 ); +extern void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose ); +/*=== 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, int nMaxLevs ); +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 int Fra_FraigMiterAssertedOutput( 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, int fProve ); +/*=== 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 nMaxLevs, 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 ); +extern Fra_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ); +extern Fra_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ); +extern void Fra_SmlFreeCounterExample( Fra_Cex_t * p ); +extern int Fra_SmlRunCounterExample( Aig_Man_t * pAig, Fra_Cex_t * p ); +extern Fra_Cex_t * Fra_SmlTrivCounterExample( Aig_Man_t * pAig, int iFrameOut ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/abc8/fra/fraBmc.c b/src/abc8/fra/fraBmc.c new file mode 100644 index 00000000..cf026fac --- /dev/null +++ b/src/abc8/fra/fraBmc.c @@ -0,0 +1,422 @@ +/**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 ); + if ( p->pAigFraig ) + 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, int fKeepPos ) +{ + 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 ); + if ( fKeepPos ) + { + for ( f = 0; f < p->nFramesAll; f++ ) + Aig_ManForEachPoSeq( p->pAig, pObj, i ) + Aig_ObjCreatePo( pAigFrames, Bmc_ObjChild0Frames(pObj,f) ); + Aig_ManCleanup( pAigFrames ); + } + else + { + // 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 = 0, 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, 0 ); + // if implications are present, configure the AIG manager to check them + if ( p->pCla->vImps ) + { + p->pBmc->pAigFrames->pImpFunc = (void (*) (void*, void*))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, 0 ); + 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; +} + +/**Function************************************************************* + + Synopsis [Performs BMC for the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose ) +{ + extern Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig ); + Fra_Man_t * pTemp; + Fra_Bmc_t * pBmc; + Aig_Man_t * pAigTemp; + int iOutput; + // derive and fraig the frames + pBmc = Fra_BmcStart( pAig, 0, nFrames ); + pTemp = Fra_LcrAigPrepare( pAig ); + pTemp->pBmc = pBmc; + pBmc->pAigFrames = Fra_BmcFrames( pBmc, 1 ); + if ( fRewrite ) + { + pBmc->pAigFrames = Dar_ManRwsat( pAigTemp = pBmc->pAigFrames, 1, 0 ); + Aig_ManStop( pAigTemp ); + } + iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFrames ); + if ( iOutput >= 0 ) + pAig->pSeqModel = Fra_SmlTrivCounterExample( pAig, iOutput ); + else + { + pBmc->pAigFraig = Fra_FraigEquivence( pBmc->pAigFrames, nBTLimit, 1 ); + iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFraig ); + if ( pBmc->pAigFraig->pData ) + { + pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pBmc->pAigFrames, pBmc->pAigFraig->pData ); + FREE( pBmc->pAigFraig->pData ); + } + else if ( iOutput >= 0 ) + pAig->pSeqModel = Fra_SmlTrivCounterExample( pAig, iOutput ); + } + if ( fVerbose ) + printf( "nFrames = %3d. Aig = %6d. Init frames = %6d. Fraiged init frames = %6d.\n", + nFrames, Aig_ManNodeNum(pAig), Aig_ManNodeNum(pBmc->pAigFrames), pBmc->pAigFraig? Aig_ManNodeNum(pBmc->pAigFraig) : -1 ); + Fra_BmcStop( pBmc ); + free( pTemp ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/fra/fraCec.c b/src/abc8/fra/fraCec.c new file mode 100644 index 00000000..bdab25dd --- /dev/null +++ b/src/abc8/fra/fraCec.c @@ -0,0 +1,303 @@ +/**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" +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigSat( Aig_Man_t * pMan, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ) +{ + sat_solver * pSat; + Cnf_Dat_t * pCnf; + int status, RetValue, clk = clock(); + Vec_Int_t * vCiIds; + + assert( Aig_ManPoNum(pMan) == 1 ); + pMan->pData = NULL; + + // derive CNF + pCnf = Cnf_Derive( pMan, 0 ); +// pCnf = Cnf_DeriveSimple( pMan, 0 ); + // convert into the SAT solver + pSat = Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + vCiIds = Cnf_DataCollectPiSatNums( pCnf, 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 ) + { + pMan->pData = 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 [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigCec( Aig_Man_t ** ppAig, int fVerbose ) +{ + int nBTLimitStart = 300; // starting SAT run + int nBTLimitFirst = 2; // first fraiging iteration + int nBTLimitLast = 1000000; // the last-gasp SAT run + + Fra_Par_t Params, * pParams = &Params; + Aig_Man_t * pAig = *ppAig, * pTemp; + int i, RetValue, clk; + + // report the original miter + if ( fVerbose ) + { + printf( "Original miter: Nodes = %6d.\n", Aig_ManNodeNum(pAig) ); + } + RetValue = Fra_FraigMiterStatus( pAig ); +// assert( RetValue == -1 ); + if ( RetValue >= 0 ) + return RetValue; + + // if SAT only, solve without iteration +clk = clock(); + RetValue = Fra_FraigSat( pAig, (sint64)2*nBTLimitStart, (sint64)0, 0 ); + if ( fVerbose ) + { + printf( "Initial SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); +PRT( "Time", clock() - clk ); + } + if ( RetValue >= 0 ) + return RetValue; + + // duplicate the AIG +clk = clock(); +// pAig = Aig_ManDup( pTemp = pAig ); + pAig = Dar_ManRwsat( pTemp = pAig, 0, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); +PRT( "Time", clock() - clk ); + } + + // perform the loop + Fra_ParamsDefault( pParams ); + pParams->nBTLimitNode = nBTLimitFirst; + pParams->nBTLimitMiter = nBTLimitStart; + pParams->fDontShowBar = 1; + pParams->fProve = 1; + for ( i = 0; i < 6; i++ ) + { +//printf( "Running fraiging with %d BTnode and %d BTmiter.\n", pParams->nBTLimitNode, pParams->nBTLimitMiter ); + // run fraiging +clk = clock(); + pAig = Fra_FraigPerform( pTemp = pAig, pParams ); + Aig_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Fraiging (i=%d): Nodes = %6d. ", i+1, Aig_ManNodeNum(pAig) ); +PRT( "Time", clock() - clk ); + } + + // check the miter status + RetValue = Fra_FraigMiterStatus( pAig ); + if ( RetValue >= 0 ) + break; + + // perform rewriting +clk = clock(); + pAig = Dar_ManRewriteDefault( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); +PRT( "Time", clock() - clk ); + } + + // check the miter status + RetValue = Fra_FraigMiterStatus( pAig ); + if ( RetValue >= 0 ) + break; + // try simulation + + // set the parameters for the next run + pParams->nBTLimitNode = 8 * pParams->nBTLimitNode; + pParams->nBTLimitMiter = 2 * pParams->nBTLimitMiter; + } + + // if still unsolved try last gasp + if ( RetValue == -1 ) + { +clk = clock(); + RetValue = Fra_FraigSat( pAig, (sint64)nBTLimitLast, (sint64)0, 0 ); + if ( fVerbose ) + { + printf( "Final SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); +PRT( "Time", clock() - clk ); + } + } + + *ppAig = pAig; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int fVerbose ) +{ + Aig_Man_t * pAig; + Vec_Ptr_t * vParts; + int i, RetValue = 1, nOutputs; + // create partitions + vParts = Aig_ManMiterPartitioned( pMan1, pMan2, 100 ); + // solve the partitions + nOutputs = -1; + Vec_PtrForEachEntry( vParts, pAig, i ) + { + nOutputs++; + if ( fVerbose ) + printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", + i+1, Vec_PtrSize(vParts), Aig_ManPiNum(pAig), Aig_ManPoNum(pAig), + Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); + RetValue = Fra_FraigMiterStatus( pAig ); + if ( RetValue == 1 ) + continue; + if ( RetValue == 0 ) + break; + RetValue = Fra_FraigCec( &pAig, 0 ); + Vec_PtrWriteEntry( vParts, i, pAig ); + if ( RetValue == 1 ) + continue; + if ( RetValue == 0 ) + break; + break; + } + // clear the result + if ( fVerbose ) + { + printf( " \r" ); + fflush( stdout ); + } + // report the timeout + if ( RetValue == -1 ) + { + printf( "Timed out after verifying %d partitions (out of %d).\n", nOutputs, Vec_PtrSize(vParts) ); + fflush( stdout ); + } + // free intermediate results + Vec_PtrForEachEntry( vParts, pAig, i ) + Aig_ManStop( pAig ); + Vec_PtrFree( vParts ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/fra/fraClass.c b/src/abc8/fra/fraClass.c new file mode 100644 index 00000000..2d03e65d --- /dev/null +++ b/src/abc8/fra/fraClass.c @@ -0,0 +1,855 @@ +/**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, int nMaxLevs ) +{ + 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 ( nMaxLevs && (int)pObj->Level >= nMaxLevs ) + 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 + cMinSupp = -1; + 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/abc8/fra/fraClau.c b/src/abc8/fra/fraClau.c new file mode 100644 index 00000000..fc239a40 --- /dev/null +++ b/src/abc8/fra/fraClau.c @@ -0,0 +1,759 @@ +/**CFile**************************************************************** + + FileName [fraClau.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Induction with clause strengthening.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" +#include "cnf.h" +#include "satSolver.h" + +/* + This code is inspired by the paper: Aaron Bradley and Zohar Manna, + "Checking safety by inductive generalization of counterexamples to + induction", FMCAD '07. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cla_Man_t_ Cla_Man_t; +struct Cla_Man_t_ +{ + // SAT solvers + sat_solver * pSatMain; + sat_solver * pSatTest; + sat_solver * pSatBmc; + // CNF for the test solver +// Cnf_Dat_t * pCnfTest; + // SAT variables + Vec_Int_t * vSatVarsMainCs; + Vec_Int_t * vSatVarsTestCs; + Vec_Int_t * vSatVarsTestNs; + Vec_Int_t * vSatVarsBmcNs; + // helper variables + int nSatVarsTestBeg; + int nSatVarsTestCur; + // counter-examples + Vec_Int_t * vCexMain0; + Vec_Int_t * vCexMain; + Vec_Int_t * vCexTest; + Vec_Int_t * vCexBase; + Vec_Int_t * vCexAssm; + Vec_Int_t * vCexBmc; + // mapping of CS into NS var numbers + int * pMapCsMainToCsTest; + int * pMapCsTestToCsMain; + int * pMapCsTestToNsTest; + int * pMapCsTestToNsBmc; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Saves variables corresponding to latch outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Fra_ClauSaveLatchVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int fCsVars ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObjLo, * pObjLi; + int i; + vVars = Vec_IntAlloc( Aig_ManRegNum(pMan) ); + Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) + Vec_IntPush( vVars, pCnf->pVarNums[fCsVars? pObjLo->Id : pObjLi->Id] ); + return vVars; +} + +/**Function************************************************************* + + Synopsis [Saves variables corresponding to latch outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Fra_ClauSaveOutputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObj; + int i; + vVars = Vec_IntAlloc( Aig_ManPoNum(pMan) ); + Aig_ManForEachPo( pMan, pObj, i ) + Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] ); + return vVars; +} + +/**Function************************************************************* + + Synopsis [Saves variables corresponding to latch outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Fra_ClauSaveInputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int nStarting ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObj; + int i; + vVars = Vec_IntAlloc( Aig_ManPiNum(pMan) - nStarting ); + Aig_ManForEachPi( pMan, pObj, i ) + { + if ( i < nStarting ) + continue; + Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] ); + } + return vVars; +} + +/**Function************************************************************* + + Synopsis [Saves variables corresponding to latch outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Fra_ClauCreateMapping( Vec_Int_t * vSatVarsFrom, Vec_Int_t * vSatVarsTo, int nVarsMax ) +{ + int * pMapping, Var, i; + assert( Vec_IntSize(vSatVarsFrom) == Vec_IntSize(vSatVarsTo) ); + pMapping = ALLOC( int, nVarsMax ); + for ( i = 0; i < nVarsMax; i++ ) + pMapping[i] = -1; + Vec_IntForEachEntry( vSatVarsFrom, Var, i ) + pMapping[Var] = Vec_IntEntry(vSatVarsTo,i); + return pMapping; +} + + +/**Function************************************************************* + + Synopsis [Deletes the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClauStop( Cla_Man_t * p ) +{ + free( p->pMapCsMainToCsTest ); + free( p->pMapCsTestToCsMain ); + free( p->pMapCsTestToNsTest ); + free( p->pMapCsTestToNsBmc ); + Vec_IntFree( p->vSatVarsMainCs ); + Vec_IntFree( p->vSatVarsTestCs ); + Vec_IntFree( p->vSatVarsTestNs ); + Vec_IntFree( p->vSatVarsBmcNs ); + Vec_IntFree( p->vCexMain0 ); + Vec_IntFree( p->vCexMain ); + Vec_IntFree( p->vCexTest ); + Vec_IntFree( p->vCexBase ); + Vec_IntFree( p->vCexAssm ); + Vec_IntFree( p->vCexBmc ); + if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); + if ( p->pSatTest ) sat_solver_delete( p->pSatTest ); + if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Takes the AIG with the single output to be checked.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cla_Man_t * Fra_ClauStart( Aig_Man_t * pMan ) +{ + Cla_Man_t * p; + Cnf_Dat_t * pCnfMain; + Cnf_Dat_t * pCnfTest; + Cnf_Dat_t * pCnfBmc; + Aig_Man_t * pFramesMain; + Aig_Man_t * pFramesTest; + Aig_Man_t * pFramesBmc; + assert( Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) == 1 ); + + // start the manager + p = ALLOC( Cla_Man_t, 1 ); + memset( p, 0, sizeof(Cla_Man_t) ); + p->vCexMain0 = Vec_IntAlloc( Aig_ManRegNum(pMan) ); + p->vCexMain = Vec_IntAlloc( Aig_ManRegNum(pMan) ); + p->vCexTest = Vec_IntAlloc( Aig_ManRegNum(pMan) ); + p->vCexBase = Vec_IntAlloc( Aig_ManRegNum(pMan) ); + p->vCexAssm = Vec_IntAlloc( Aig_ManRegNum(pMan) ); + p->vCexBmc = Vec_IntAlloc( Aig_ManRegNum(pMan) ); + + // derive two timeframes to be checked + pFramesMain = Aig_ManFrames( pMan, 2, 0, 1, 0, 0, NULL ); // nFrames, fInit, fOuts, fRegs +//Aig_ManShow( pFramesMain, 0, NULL ); + assert( Aig_ManPoNum(pFramesMain) == 2 ); + Aig_ObjChild0Flip( Aig_ManPo(pFramesMain, 0) ); // complement the first output + pCnfMain = Cnf_DeriveSimple( pFramesMain, 0 ); +//Cnf_DataWriteIntoFile( pCnfMain, "temp.cnf", 1 ); + p->pSatMain = Cnf_DataWriteIntoSolver( pCnfMain, 1, 0 ); +/* + { + int i; + Aig_Obj_t * pObj; + Aig_ManForEachObj( pFramesMain, pObj, i ) + printf( "%d -> %d \n", pObj->Id, pCnfMain->pVarNums[pObj->Id] ); + printf( "\n" ); + } +*/ + + // derive one timeframe to be checked + pFramesTest = Aig_ManFrames( pMan, 1, 0, 0, 1, 0, NULL ); + assert( Aig_ManPoNum(pFramesTest) == Aig_ManRegNum(pMan) ); + pCnfTest = Cnf_DeriveSimple( pFramesTest, Aig_ManRegNum(pMan) ); + p->pSatTest = Cnf_DataWriteIntoSolver( pCnfTest, 1, 0 ); + p->nSatVarsTestBeg = p->nSatVarsTestCur = sat_solver_nvars( p->pSatTest ); + + // derive one timeframe to be checked for BMC + pFramesBmc = Aig_ManFrames( pMan, 1, 1, 0, 1, 0, NULL ); +//Aig_ManShow( pFramesBmc, 0, NULL ); + assert( Aig_ManPoNum(pFramesBmc) == Aig_ManRegNum(pMan) ); + pCnfBmc = Cnf_DeriveSimple( pFramesBmc, Aig_ManRegNum(pMan) ); + p->pSatBmc = Cnf_DataWriteIntoSolver( pCnfBmc, 1, 0 ); + + // create variable sets + p->vSatVarsMainCs = Fra_ClauSaveInputVars( pFramesMain, pCnfMain, 2 * (Aig_ManPiNum(pMan)-Aig_ManRegNum(pMan)) ); + p->vSatVarsTestCs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 1 ); + p->vSatVarsTestNs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 0 ); + p->vSatVarsBmcNs = Fra_ClauSaveOutputVars( pFramesBmc, pCnfBmc ); + assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsMainCs) ); + assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsBmcNs) ); + + // create mapping of CS into NS vars + p->pMapCsMainToCsTest = Fra_ClauCreateMapping( p->vSatVarsMainCs, p->vSatVarsTestCs, Aig_ManObjNumMax(pFramesMain) ); + p->pMapCsTestToCsMain = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsMainCs, Aig_ManObjNumMax(pFramesTest) ); + p->pMapCsTestToNsTest = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsTestNs, Aig_ManObjNumMax(pFramesTest) ); + p->pMapCsTestToNsBmc = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsBmcNs, Aig_ManObjNumMax(pFramesTest) ); + + // cleanup + Cnf_DataFree( pCnfMain ); + Cnf_DataFree( pCnfTest ); + Cnf_DataFree( pCnfBmc ); + Aig_ManStop( pFramesMain ); + Aig_ManStop( pFramesTest ); + Aig_ManStop( pFramesBmc ); + if ( p->pSatMain == NULL || p->pSatTest == NULL || p->pSatBmc == NULL ) + { + Fra_ClauStop( p ); + return NULL; + } + return p; +} + +/**Function************************************************************* + + Synopsis [Splits off second half and returns it as a new vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Int_t * Vec_IntSplitHalf( Vec_Int_t * vVec ) +{ + Vec_Int_t * vPart; + int Entry, i; + assert( Vec_IntSize(vVec) > 1 ); + vPart = Vec_IntAlloc( Vec_IntSize(vVec) / 2 + 1 ); + Vec_IntForEachEntryStart( vVec, Entry, i, Vec_IntSize(vVec) / 2 ) + Vec_IntPush( vPart, Entry ); + Vec_IntShrink( vVec, Vec_IntSize(vVec) / 2 ); + return vPart; +} + +/**Function************************************************************* + + Synopsis [Appends the contents of the second vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 ) +{ + int Entry, i; + Vec_IntForEachEntry( vVec2, Entry, i ) + Vec_IntPush( vVec1, Entry ); +} + +/**Function************************************************************* + + Synopsis [Complements all literals in the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Vec_IntComplement( Vec_Int_t * vVec ) +{ + int i; + for ( i = 0; i < Vec_IntSize(vVec); i++ ) + vVec->pArray[i] = lit_neg( vVec->pArray[i] ); +} + +/**Function************************************************************* + + Synopsis [Checks if the property holds. Returns counter-example if not.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClauCheckProperty( Cla_Man_t * p, Vec_Int_t * vCex ) +{ + int nBTLimit = 0; + int RetValue, iVar, i; + sat_solver_act_var_clear( p->pSatMain ); + RetValue = sat_solver_solve( p->pSatMain, NULL, NULL, (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + Vec_IntClear( vCex ); + if ( RetValue == l_False ) + return 1; + assert( RetValue == l_True ); + Vec_IntForEachEntry( p->vSatVarsMainCs, iVar, i ) + Vec_IntPush( vCex, sat_solver_var_literal(p->pSatMain, iVar) ); +/* + { + int i; + for (i = 0; i < p->pSatMain->size; i++) + printf( "%d=%d ", i, p->pSatMain->model.ptr[i] == l_True ); + printf( "\n" ); + } +*/ + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the clause holds using BMC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClauCheckBmc( Cla_Man_t * p, Vec_Int_t * vClause ) +{ + int nBTLimit = 0; + int RetValue; + RetValue = sat_solver_solve( p->pSatBmc, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause), + (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + if ( RetValue == l_False ) + return 1; + assert( RetValue == l_True ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Lifts the clause to depend on NS variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClauRemapClause( int * pMap, Vec_Int_t * vClause, Vec_Int_t * vRemapped, int fInv ) +{ + int iLit, i; + Vec_IntClear( vRemapped ); + Vec_IntForEachEntry( vClause, iLit, i ) + { + assert( pMap[lit_var(iLit)] >= 0 ); + iLit = toLitCond( pMap[lit_var(iLit)], lit_sign(iLit) ^ fInv ); + Vec_IntPush( vRemapped, iLit ); + } +} + +/**Function************************************************************* + + Synopsis [Checks if the clause holds. Returns counter example if not.] + + Description [Uses test SAT solver.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClauCheckClause( Cla_Man_t * p, Vec_Int_t * vClause, Vec_Int_t * vCex ) +{ + int nBTLimit = 0; + int RetValue, iVar, i; + int nClauseSize = Vec_IntSize( vClause ); + // complement literals + Vec_IntPush( vClause, toLit( p->nSatVarsTestCur++ ) ); // helper positive + Vec_IntComplement( vClause ); // helper negative (the clause is C v h') + // add the clause + RetValue = sat_solver_addclause( p->pSatTest, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) ); + assert( RetValue == 1 ); + // complement all literals + Vec_IntPop( vClause ); // helper removed + Vec_IntComplement( vClause ); + // create the assumption in terms of NS variables + Fra_ClauRemapClause( p->pMapCsTestToNsTest, vClause, p->vCexAssm, 0 ); + // add helper literals + for ( i = p->nSatVarsTestBeg; i < p->nSatVarsTestCur - 1; i++ ) + Vec_IntPush( p->vCexAssm, toLitCond(i,1) ); // other helpers negative + Vec_IntPush( p->vCexAssm, toLitCond(i,0) ); // positive helper + // try to solve + RetValue = sat_solver_solve( p->pSatTest, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm), + (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + if ( vCex ) + Vec_IntClear( vCex ); + if ( RetValue == l_False ) + return 1; + assert( RetValue == l_True ); + if ( vCex ) + { + Vec_IntForEachEntry( p->vSatVarsTestCs, iVar, i ) + Vec_IntPush( vCex, sat_solver_var_literal(p->pSatTest, iVar) ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Reduces the counter-example by removing complemented literals.] + + Description [Removes literals from vMain that differ from those in the + counter-example (vNew). Relies on the fact that the PI variables are + assigned in the increasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClauReduceClause( Vec_Int_t * vMain, Vec_Int_t * vNew ) +{ + int LitM, LitN, VarM, VarN, i, j, k; + assert( Vec_IntSize(vMain) <= Vec_IntSize(vNew) ); + for ( i = j = k = 0; i < Vec_IntSize(vMain) && j < Vec_IntSize(vNew); ) + { + LitM = Vec_IntEntry( vMain, i ); + LitN = Vec_IntEntry( vNew, j ); + VarM = lit_var( LitM ); + VarN = lit_var( LitN ); + if ( VarM < VarN ) + { + assert( 0 ); + } + else if ( VarM > VarN ) + { + j++; + } + else // if ( VarM == VarN ) + { + i++; + j++; + if ( LitM == LitN ) + Vec_IntWriteEntry( vMain, k++, LitM ); + } + } + assert( i == Vec_IntSize(vMain) ); + Vec_IntShrink( vMain, k ); +} + +/**Function************************************************************* + + Synopsis [Computes the minimal invariant that holds.] + + Description [On entrace, vBasis does not hold, vBasis+vExtra holds but + is not minimal. On exit, vBasis is unchanged, vBasis+vExtra is minimal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClauMinimizeClause_rec( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra ) +{ + Vec_Int_t * vExtra2; + int nSizeOld; + if ( Vec_IntSize(vExtra) == 1 ) + return; + nSizeOld = Vec_IntSize( vBasis ); + vExtra2 = Vec_IntSplitHalf( vExtra ); + + // try the first half + Vec_IntAppend( vBasis, vExtra ); + if ( Fra_ClauCheckClause( p, vBasis, NULL ) ) + { + Vec_IntShrink( vBasis, nSizeOld ); + Fra_ClauMinimizeClause_rec( p, vBasis, vExtra ); + return; + } + Vec_IntShrink( vBasis, nSizeOld ); + + // try the second half + Vec_IntAppend( vBasis, vExtra2 ); + if ( Fra_ClauCheckClause( p, vBasis, NULL ) ) + { + Vec_IntShrink( vBasis, nSizeOld ); + Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 ); + return; + } +// Vec_IntShrink( vBasis, nSizeOld ); + + // find the smallest with the second half added + Fra_ClauMinimizeClause_rec( p, vBasis, vExtra ); + Vec_IntShrink( vBasis, nSizeOld ); + Vec_IntAppend( vBasis, vExtra ); + // find the smallest with the second half added + Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 ); + Vec_IntShrink( vBasis, nSizeOld ); + Vec_IntAppend( vExtra, vExtra2 ); + Vec_IntFree( vExtra2 ); +} + +/**Function************************************************************* + + Synopsis [Minimizes the clauses using a simple method.] + + Description [The input and output clause are in vExtra.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClauMinimizeClause( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra ) +{ + int iLit, iLit2, i, k; + Vec_IntForEachEntryReverse( vExtra, iLit, i ) + { + // copy literals without the given one + Vec_IntClear( vBasis ); + Vec_IntForEachEntry( vExtra, iLit2, k ) + if ( k != i ) + Vec_IntPush( vBasis, iLit2 ); + // try whether it is inductive + if ( !Fra_ClauCheckClause( p, vBasis, NULL ) ) + continue; + // the clause is inductive + // remove the literal + for ( k = i; k < Vec_IntSize(vExtra)-1; k++ ) + Vec_IntWriteEntry( vExtra, k, Vec_IntEntry(vExtra,k+1) ); + Vec_IntShrink( vExtra, Vec_IntSize(vExtra)-1 ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClauPrintClause( Vec_Int_t * vSatCsVars, Vec_Int_t * vCex ) +{ + int LitM, VarM, VarN, i, j, k; + assert( Vec_IntSize(vCex) <= Vec_IntSize(vSatCsVars) ); + for ( i = j = k = 0; i < Vec_IntSize(vCex) && j < Vec_IntSize(vSatCsVars); ) + { + LitM = Vec_IntEntry( vCex, i ); + VarM = lit_var( LitM ); + VarN = Vec_IntEntry( vSatCsVars, j ); + if ( VarM < VarN ) + { + assert( 0 ); + } + else if ( VarM > VarN ) + { + j++; + printf( "-" ); + } + else // if ( VarM == VarN ) + { + i++; + j++; + printf( "%d", !lit_sign(LitM) ); + } + } + assert( i == Vec_IntSize(vCex) ); +} + +/**Function************************************************************* + + Synopsis [Takes the AIG with the single output to be checked.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose ) +{ + Cla_Man_t * p; + int Iter, RetValue, fFailed, i; + assert( Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) == 1 ); + // create the manager + p = Fra_ClauStart( pMan ); + if ( p == NULL ) + { + printf( "The property is trivially inductive.\n" ); + return 1; + } + // generate counter-examples and expand them + for ( Iter = 0; !Fra_ClauCheckProperty( p, p->vCexMain0 ) && Iter < nIters; Iter++ ) + { + if ( fVerbose ) + printf( "%4d : ", Iter ); + // remap clause into the test manager + Fra_ClauRemapClause( p->pMapCsMainToCsTest, p->vCexMain0, p->vCexMain, 0 ); + if ( fVerbose && fVeryVerbose ) + Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); + // the main counter-example is in p->vCexMain + // intermediate counter-examples are in p->vCexTest + // generate the reduced counter-example to the inductive property + fFailed = 0; + for ( i = 0; !Fra_ClauCheckClause( p, p->vCexMain, p->vCexTest ); i++ ) + { + Fra_ClauReduceClause( p->vCexMain, p->vCexTest ); + Fra_ClauRemapClause( p->pMapCsTestToNsBmc, p->vCexMain, p->vCexBmc, 0 ); + +// if ( !Fra_ClauCheckBmc(p, p->vCexBmc) ) + if ( Vec_IntSize(p->vCexMain) < 1 ) + { + Vec_IntComplement( p->vCexMain0 ); + RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexMain0), Vec_IntArray(p->vCexMain0) + Vec_IntSize(p->vCexMain0) ); + if ( RetValue == 0 ) + { + printf( "\nProperty is proved after %d iterations.\n", Iter+1 ); + return 0; + } + fFailed = 1; + break; + } + } + if ( fFailed ) + { + if ( fVerbose ) + printf( " Reducing failed after %d iterations (BMC failed).\n", i ); + continue; + } + if ( Vec_IntSize(p->vCexMain) == 0 ) + { + if ( fVerbose ) + printf( " Reducing failed after %d iterations (nothing left).\n", i ); + continue; + } + if ( fVerbose ) + printf( " " ); + if ( fVerbose && fVeryVerbose ) + Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); + if ( fVerbose ) + printf( " LitsInd = %3d. ", Vec_IntSize(p->vCexMain) ); + // minimize the inductive property + Vec_IntClear( p->vCexBase ); + if ( Vec_IntSize(p->vCexMain) > 1 ) +// Fra_ClauMinimizeClause_rec( p, p->vCexBase, p->vCexMain ); + Fra_ClauMinimizeClause( p, p->vCexBase, p->vCexMain ); + assert( Vec_IntSize(p->vCexMain) > 0 ); + if ( fVerbose && fVeryVerbose ) + Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); + if ( fVerbose ) + printf( " LitsRed = %3d. ", Vec_IntSize(p->vCexMain) ); + if ( fVerbose ) + printf( "\n" ); + // add the clause to the solver + Fra_ClauRemapClause( p->pMapCsTestToCsMain, p->vCexMain, p->vCexAssm, 1 ); + RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm) ); + if ( RetValue == 0 ) + { + Iter++; + break; + } + if ( p->pSatMain->qtail != p->pSatMain->qhead ) + { + RetValue = sat_solver_simplify(p->pSatMain); + assert( RetValue != 0 ); + assert( p->pSatMain->qtail == p->pSatMain->qhead ); + } + } + + // report the results + if ( Iter == nIters ) + { + printf( "Property is not proved after %d iterations.\n", nIters ); + return 0; + } + printf( "Property is proved after %d iterations.\n", Iter ); + Fra_ClauStop( p ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/fra/fraClaus.c b/src/abc8/fra/fraClaus.c new file mode 100644 index 00000000..e5b8a126 --- /dev/null +++ b/src/abc8/fra/fraClaus.c @@ -0,0 +1,1766 @@ +/**CFile**************************************************************** + + FileName [fraClaus.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Induction with clause strengthening.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" +#include "cnf.h" +#include "satSolver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Clu_Man_t_ Clu_Man_t; +struct Clu_Man_t_ +{ + // parameters + int nFrames; // the K of the K-step induction + int nPref; // the number of timeframes to skip + int nClausesMax; // the max number of 4-clauses to consider + int nLutSize; // the max cut size + int nLevels; // the number of levels for cut computation + int nCutsMax; // the maximum number of cuts to compute at a node + int nBatches; // the number of clause batches to use + int fStepUp; // increase cut size for each batch + int fTarget; // tries to prove the property + int fVerbose; + int fVeryVerbose; + // internal parameters + int nSimWords; // the number of simulation words + int nSimWordsPref; // the number of simulation words in the prefix + int nSimFrames; // the number of frames to simulate + int nBTLimit; // the largest number of backtracks (0 = infinite) + // the network + Aig_Man_t * pAig; + // SAT solvers + sat_solver * pSatMain; + sat_solver * pSatBmc; + // CNF for the test solver + Cnf_Dat_t * pCnf; + int fFail; + int fFiltering; + int fNothingNew; + // clauses + Vec_Int_t * vLits; + Vec_Int_t * vClauses; + Vec_Int_t * vCosts; + int nClauses; + int nCuts; + int nOneHots; + int nOneHotsProven; + // clauses proven + Vec_Int_t * vLitsProven; + Vec_Int_t * vClausesProven; + int nClausesProven; + // counter-examples + Vec_Ptr_t * vCexes; + int nCexes; + int nCexesAlloc; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Runs the SAT solver on the problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausRunBmc( Clu_Man_t * p ) +{ + Aig_Obj_t * pObj; + int Lits[2], nLitsTot, RetValue, i; + // set the output literals + nLitsTot = 2 * p->pCnf->nVars; + pObj = Aig_ManPo(p->pAig, 0); + for ( i = 0; i < p->nPref + p->nFrames; i++ ) + { + Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 0 ); + RetValue = sat_solver_solve( p->pSatBmc, Lits, Lits + 1, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + if ( RetValue != l_False ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Runs the SAT solver on the problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausRunSat( Clu_Man_t * p ) +{ + Aig_Obj_t * pObj; + int * pLits; + int i, RetValue; + pLits = ALLOC( int, p->nFrames + 1 ); + // set the output literals + pObj = Aig_ManPo(p->pAig, 0); + for ( i = 0; i <= p->nFrames; i++ ) + pLits[i] = i * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObj->Id], i != p->nFrames ); + // try to solve the problem + RetValue = sat_solver_solve( p->pSatMain, pLits, pLits + p->nFrames + 1, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + free( pLits ); + if ( RetValue == l_False ) + return 1; + // get the counter-example + assert( RetValue == l_True ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Runs the SAT solver on the problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausRunSat0( Clu_Man_t * p ) +{ + Aig_Obj_t * pObj; + int Lits[2], RetValue; + pObj = Aig_ManPo(p->pAig, 0); + Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 0 ); + RetValue = sat_solver_solve( p->pSatMain, Lits, Lits + 1, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + if ( RetValue == l_False ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Return combinations appearing in the cut.] + + Description [This procedure is taken from "Hacker's Delight" by H.S.Warren.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void transpose32a( unsigned a[32] ) +{ + int j, k; + unsigned long m, t; + for ( j = 16, m = 0x0000FFFF; j; j >>= 1, m ^= m << j ) + { + for ( k = 0; k < 32; k = ((k | j) + 1) & ~j ) + { + t = (a[k] ^ (a[k|j] >> j)) & m; + a[k] ^= t; + a[k|j] ^= (t << j); + } + } +} + +/**Function************************************************************* + + Synopsis [Return combinations appearing in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausProcessClausesCut( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores ) +{ + unsigned Matrix[32]; + unsigned * pSims[16], uWord; + int nSeries, i, k, j; + int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; + // compute parameters + assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 ); + assert( nWordsForSim % 8 == 0 ); + // get parameters + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref; + // add combinational patterns + memset( pScores, 0, sizeof(int) * 16 ); + nSeries = nWordsForSim / 8; + for ( i = 0; i < nSeries; i++ ) + { + memset( Matrix, 0, sizeof(unsigned) * 32 ); + for ( k = 0; k < 8; k++ ) + for ( j = 0; j < (int)pCut->nLeaves; j++ ) + Matrix[31-(k*4+j)] = pSims[j][i*8+k]; + transpose32a( Matrix ); + for ( k = 0; k < 32; k++ ) + for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 ) + pScores[uWord & 0xF]++; + } + // collect patterns + uWord = 0; + for ( i = 0; i < 16; i++ ) + if ( pScores[i] ) + uWord |= (1 << i); +// Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" ); + return (int)uWord; +} + +/**Function************************************************************* + + Synopsis [Return combinations appearing in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausProcessClausesCut2( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores ) +{ + unsigned * pSims[16], uWord; + int iMint, i, k, b; + int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; + // compute parameters + assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 ); + assert( nWordsForSim % 8 == 0 ); + // get parameters + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref; + // add combinational patterns + memset( pScores, 0, sizeof(int) * 16 ); + for ( i = 0; i < nWordsForSim; i++ ) + for ( k = 0; k < 32; k++ ) + { + iMint = 0; + for ( b = 0; b < (int)pCut->nLeaves; b++ ) + if ( pSims[b][i] & (1 << k) ) + iMint |= (1 << b); + pScores[iMint]++; + } + // collect patterns + uWord = 0; + for ( i = 0; i < 16; i++ ) + if ( pScores[i] ) + uWord |= (1 << i); +// Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" ); + return (int)uWord; +} + +/**Function************************************************************* + + Synopsis [Return the number of combinations appearing in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausProcessClausesCut3( Clu_Man_t * p, Fra_Sml_t * pSimMan, Aig_Cut_t * pCut, int * pScores ) +{ + unsigned Matrix[32]; + unsigned * pSims[16], uWord; + int iMint, i, j, k, b, nMints, nSeries; + int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; + + // compute parameters + assert( pCut->nFanins > 1 && pCut->nFanins < 17 ); + assert( nWordsForSim % 8 == 0 ); + // get parameters + for ( i = 0; i < (int)pCut->nFanins; i++ ) + pSims[i] = Fra_ObjSim( pSimMan, pCut->pFanins[i] ) + p->nSimWordsPref; + // add combinational patterns + nMints = (1 << pCut->nFanins); + memset( pScores, 0, sizeof(int) * nMints ); + + if ( pCut->nLeafMax == 4 ) + { + // convert the simulation patterns + nSeries = nWordsForSim / 8; + for ( i = 0; i < nSeries; i++ ) + { + memset( Matrix, 0, sizeof(unsigned) * 32 ); + for ( k = 0; k < 8; k++ ) + for ( j = 0; j < (int)pCut->nFanins; j++ ) + Matrix[31-(k*4+j)] = pSims[j][i*8+k]; + transpose32a( Matrix ); + for ( k = 0; k < 32; k++ ) + for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 ) + pScores[uWord & 0xF]++; + } + } + else + { + // go through the simulation patterns + for ( i = 0; i < nWordsForSim; i++ ) + for ( k = 0; k < 32; k++ ) + { + iMint = 0; + for ( b = 0; b < (int)pCut->nFanins; b++ ) + if ( pSims[b][i] & (1 << k) ) + iMint |= (1 << b); + pScores[iMint]++; + } + } +} + + +/**Function************************************************************* + + Synopsis [Returns the cut-off cost.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausSelectClauses( Clu_Man_t * p ) +{ + int * pCostCount, nClauCount, Cost, CostMax, i, c; + assert( Vec_IntSize(p->vClauses) > p->nClausesMax ); + // count how many implications have each cost + CostMax = p->nSimWords * 32 + 1; + pCostCount = ALLOC( int, CostMax ); + memset( pCostCount, 0, sizeof(int) * CostMax ); + Vec_IntForEachEntry( p->vCosts, Cost, i ) + { + if ( Cost == -1 ) + continue; + assert( Cost < CostMax ); + pCostCount[ Cost ]++; + } + assert( pCostCount[0] == 0 ); + // select the bound on the cost (above this bound, implication will be included) + nClauCount = 0; + for ( c = CostMax - 1; c > 0; c-- ) + { + assert( pCostCount[c] >= 0 ); + nClauCount += pCostCount[c]; + if ( nClauCount >= p->nClausesMax ) + break; + } + // collect implications with the given costs + nClauCount = 0; + Vec_IntForEachEntry( p->vCosts, Cost, i ) + { + if ( Cost >= c && nClauCount < p->nClausesMax ) + { + nClauCount++; + continue; + } + Vec_IntWriteEntry( p->vCosts, i, -1 ); + } + free( pCostCount ); + p->nClauses = nClauCount; +if ( p->fVerbose ) +printf( "Selected %d clauses. Cost range: [%d < %d < %d]\n", nClauCount, 1, c, CostMax ); + return c; +} + + +/**Function************************************************************* + + Synopsis [Processes the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausRecordClause( Clu_Man_t * p, Dar_Cut_t * pCut, int iMint, int Cost ) +{ + int i; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pLeaves[i]], (iMint&(1<vClauses, Vec_IntSize(p->vLits) ); + Vec_IntPush( p->vCosts, Cost ); +} + +/**Function************************************************************* + + Synopsis [Processes the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausRecordClause2( Clu_Man_t * p, Aig_Cut_t * pCut, int iMint, int Cost ) +{ + int i; + for ( i = 0; i < (int)pCut->nFanins; i++ ) + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pFanins[i]], (iMint&(1<vClauses, Vec_IntSize(p->vLits) ); + Vec_IntPush( p->vCosts, Cost ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausSmlNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i; + pSims = Fra_ObjSim(pSeq, pObj->Id); + for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ ) + if ( pSims[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if implications holds.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausSmlNodesAreImp( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) +{ + unsigned * pSimL, * pSimR; + int k; + pSimL = Fra_ObjSim(pSeq, pObj1->Id); + pSimR = Fra_ObjSim(pSeq, pObj2->Id); + for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) + if ( pSimL[k] & ~pSimR[k] ) // !(Obj1 -> Obj2) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if implications holds.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausSmlNodesAreImpC( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) +{ + unsigned * pSimL, * pSimR; + int k; + pSimL = Fra_ObjSim(pSeq, pObj1->Id); + pSimR = Fra_ObjSim(pSeq, pObj2->Id); + for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) + if ( pSimL[k] & pSimR[k] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Processes the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausCollectLatchClauses( Clu_Man_t * p, Fra_Sml_t * pSeq ) +{ + Aig_Obj_t * pObj1, * pObj2; + unsigned * pSims1, * pSims2; + int CostMax, i, k, nCountConst, nCountImps; + + nCountConst = nCountImps = 0; + CostMax = p->nSimWords * 32; + pSeq->nWordsPref = p->nSimWordsPref; + Aig_ManForEachLoSeq( p->pAig, pObj1, i ) + { + pSims1 = Fra_ObjSim( pSeq, pObj1->Id ); + if ( Fra_ClausSmlNodeIsConst( pSeq, pObj1 ) ) + { + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); + Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); + Vec_IntPush( p->vCosts, CostMax ); + nCountConst++; + continue; + } + Aig_ManForEachLoSeq( p->pAig, pObj2, k ) + { + pSims2 = Fra_ObjSim( pSeq, pObj2->Id ); + if ( Fra_ClausSmlNodesAreImp( pSeq, pObj1, pObj2 ) ) + { + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 0 ) ); + Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); + Vec_IntPush( p->vCosts, CostMax ); + nCountImps++; + continue; + } + if ( Fra_ClausSmlNodesAreImp( pSeq, pObj2, pObj1 ) ) + { + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) ); + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 0 ) ); + Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); + Vec_IntPush( p->vCosts, CostMax ); + nCountImps++; + continue; + } + if ( Fra_ClausSmlNodesAreImpC( pSeq, pObj1, pObj2 ) ) + { + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); + Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) ); + Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); + Vec_IntPush( p->vCosts, CostMax ); + nCountImps++; + continue; + } + } + if ( nCountConst + nCountImps > p->nClausesMax / 2 ) + break; + } + pSeq->nWordsPref = 0; + if ( p->fVerbose ) + printf( "Collected %d register constants and %d one-hotness implications.\n", nCountConst, nCountImps ); + p->nOneHots = nCountConst + nCountImps; + p->nOneHotsProven = 0; + return 0; +} + +/**Function************************************************************* + + Synopsis [Processes the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausProcessClauses( Clu_Man_t * p, int fRefs ) +{ + Aig_MmFixed_t * pMemCuts; +// Aig_ManCut_t * pManCut; + Fra_Sml_t * pComb, * pSeq; + Aig_Obj_t * pObj; + Dar_Cut_t * pCut; + int Scores[16], uScores, i, k, j, clk, nCuts = 0; + + // simulate the AIG +clk = clock(); + srand( 0xAABBAABB ); + pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames ); + if ( p->fTarget && pSeq->fNonConstOut ) + { + printf( "Property failed after sequential simulation!\n" ); + Fra_SmlStop( pSeq ); + return 0; + } +if ( p->fVerbose ) +{ +PRT( "Sim-seq", clock() - clk ); +} + + +clk = clock(); + if ( fRefs ) + { + Fra_ClausCollectLatchClauses( p, pSeq ); +if ( p->fVerbose ) +{ +PRT( "Lat-cla", clock() - clk ); +} + } + + + // generate cuts for all nodes, assign cost, and find best cuts +clk = clock(); + pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 1 ); +// pManCut = Aig_ComputeCuts( p->pAig, 10, 4, 0, 1 ); +if ( p->fVerbose ) +{ +PRT( "Cuts ", clock() - clk ); +} + + // collect sequential info for each cut +clk = clock(); + Aig_ManForEachNode( p->pAig, pObj, i ) + Dar_ObjForEachCut( pObj, pCut, k ) + if ( pCut->nLeaves > 1 ) + { + pCut->uTruth = Fra_ClausProcessClausesCut( p, pSeq, pCut, Scores ); +// uScores = Fra_ClausProcessClausesCut2( p, pSeq, pCut, Scores ); +// if ( uScores != pCut->uTruth ) +// { +// int x = 0; +// } + } +if ( p->fVerbose ) +{ +PRT( "Infoseq", clock() - clk ); +} + Fra_SmlStop( pSeq ); + + // perform combinational simulation +clk = clock(); + srand( 0xAABBAABB ); + pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref ); +if ( p->fVerbose ) +{ +PRT( "Sim-cmb", clock() - clk ); +} + + // collect combinational info for each cut +clk = clock(); + Aig_ManForEachNode( p->pAig, pObj, i ) + Dar_ObjForEachCut( pObj, pCut, k ) + if ( pCut->nLeaves > 1 ) + { + nCuts++; + uScores = Fra_ClausProcessClausesCut( p, pComb, pCut, Scores ); + uScores &= ~pCut->uTruth; pCut->uTruth = 0; + if ( uScores == 0 ) + continue; + // write the clauses + for ( j = 0; j < (1<nLeaves); j++ ) + if ( uScores & (1 << j) ) + Fra_ClausRecordClause( p, pCut, j, Scores[j] ); + + } + Fra_SmlStop( pComb ); + Aig_MmFixedStop( pMemCuts, 0 ); +// Aig_ManCutStop( pManCut ); +if ( p->fVerbose ) +{ +PRT( "Infocmb", clock() - clk ); +} + + if ( p->fVerbose ) + printf( "Node = %5d. Non-triv cuts = %7d. Clauses = %6d. Clause per cut = %6.2f.\n", + Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts ); + + if ( Vec_IntSize(p->vClauses) > p->nClausesMax ) + Fra_ClausSelectClauses( p ); + else + p->nClauses = Vec_IntSize( p->vClauses ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Processes the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausProcessClauses2( Clu_Man_t * p, int fRefs ) +{ +// Aig_MmFixed_t * pMemCuts; + Aig_ManCut_t * pManCut; + Fra_Sml_t * pComb, * pSeq; + Aig_Obj_t * pObj; + Aig_Cut_t * pCut; + int i, k, j, clk, nCuts = 0; + int ScoresSeq[1<<12], ScoresComb[1<<12]; + assert( p->nLutSize < 13 ); + + // simulate the AIG +clk = clock(); + srand( 0xAABBAABB ); + pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames ); + if ( p->fTarget && pSeq->fNonConstOut ) + { + printf( "Property failed after sequential simulation!\n" ); + Fra_SmlStop( pSeq ); + return 0; + } +if ( p->fVerbose ) +{ +//PRT( "Sim-seq", clock() - clk ); +} + + // perform combinational simulation +clk = clock(); + srand( 0xAABBAABB ); + pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref ); +if ( p->fVerbose ) +{ +//PRT( "Sim-cmb", clock() - clk ); +} + + +clk = clock(); + if ( fRefs ) + { + Fra_ClausCollectLatchClauses( p, pSeq ); +if ( p->fVerbose ) +{ +//PRT( "Lat-cla", clock() - clk ); +} + } + + + // generate cuts for all nodes, assign cost, and find best cuts +clk = clock(); +// pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 1 ); + pManCut = Aig_ComputeCuts( p->pAig, p->nCutsMax, p->nLutSize, 0, p->fVerbose ); +if ( p->fVerbose ) +{ +//PRT( "Cuts ", clock() - clk ); +} + + // collect combinational info for each cut +clk = clock(); + Aig_ManForEachNode( p->pAig, pObj, i ) + { + if ( pObj->Level > (unsigned)p->nLevels ) + continue; + Aig_ObjForEachCut( pManCut, pObj, pCut, k ) + if ( pCut->nFanins > 1 ) + { + nCuts++; + Fra_ClausProcessClausesCut3( p, pSeq, pCut, ScoresSeq ); + Fra_ClausProcessClausesCut3( p, pComb, pCut, ScoresComb ); + // write the clauses + for ( j = 0; j < (1<nFanins); j++ ) + if ( ScoresComb[j] != 0 && ScoresSeq[j] == 0 ) + Fra_ClausRecordClause2( p, pCut, j, ScoresComb[j] ); + + } + } + Fra_SmlStop( pSeq ); + Fra_SmlStop( pComb ); + p->nCuts = nCuts; +// Aig_MmFixedStop( pMemCuts, 0 ); + Aig_ManCutStop( pManCut ); + p->pAig->pManCuts = NULL; + + if ( p->fVerbose ) + { + printf( "Node = %5d. Cuts = %7d. Clauses = %6d. Clause/cut = %6.2f.\n", + Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts ); + PRT( "Processing sim-info to find candidate clauses (unoptimized)", clock() - clk ); + } + + // filter out clauses that are contained in the already proven clauses + assert( p->nClauses == 0 ); + p->nClauses = Vec_IntSize( p->vClauses ); + if ( Vec_IntSize( p->vClausesProven ) > 0 ) + { + int RetValue, k, Beg, End, * pStart; + // reset the solver + if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); + p->pSatMain = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); + if ( p->pSatMain == NULL ) + { + printf( "Error: Main solver is unsat.\n" ); + return -1; + } + + // add the proven clauses + Beg = 0; + pStart = Vec_IntArray(p->vLitsProven); + Vec_IntForEachEntry( p->vClausesProven, End, i ) + { + assert( End - Beg <= p->nLutSize ); + // add the clause to all timeframes + RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); + if ( RetValue == 0 ) + { + printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); + return -1; + } + Beg = End; + } + assert( End == Vec_IntSize(p->vLitsProven) ); + + // check the clauses + Beg = 0; + pStart = Vec_IntArray(p->vLits); + Vec_IntForEachEntry( p->vClauses, End, i ) + { + assert( Vec_IntEntry( p->vCosts, i ) >= 0 ); + assert( End - Beg <= p->nLutSize ); + // check the clause + for ( k = Beg; k < End; k++ ) + pStart[k] = lit_neg( pStart[k] ); + RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + for ( k = Beg; k < End; k++ ) + pStart[k] = lit_neg( pStart[k] ); + // the clause holds + if ( RetValue == l_False ) + { + Vec_IntWriteEntry( p->vCosts, i, -1 ); + p->nClauses--; + } + Beg = End; + } + assert( End == Vec_IntSize(p->vLits) ); + if ( p->fVerbose ) + printf( "Already proved clauses filtered out %d candidate clauses (out of %d).\n", + Vec_IntSize(p->vClauses) - p->nClauses, Vec_IntSize(p->vClauses) ); + } + + p->fFiltering = 0; + if ( p->nClauses > p->nClausesMax ) + { + Fra_ClausSelectClauses( p ); + p->fFiltering = 1; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausBmcClauses( Clu_Man_t * p ) +{ + int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f; +/* + for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) + printf( "%d ", p->vLits->pArray[i] ); + printf( "\n" ); +*/ + // add the clauses + Counter = 0; + // skip through the prefix variables + if ( p->nPref ) + { + nLitsTot = p->nPref * 2 * p->pCnf->nVars; + for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) + p->vLits->pArray[i] += nLitsTot; + } + // go through the timeframes + nLitsTot = 2 * p->pCnf->nVars; + pStart = Vec_IntArray(p->vLits); + for ( f = 0; f < p->nFrames; f++ ) + { + Beg = 0; + Vec_IntForEachEntry( p->vClauses, End, i ) + { + if ( Vec_IntEntry( p->vCosts, i ) == -1 ) + { + Beg = End; + continue; + } + assert( Vec_IntEntry( p->vCosts, i ) > 0 ); + assert( End - Beg <= p->nLutSize ); + + for ( k = Beg; k < End; k++ ) + pStart[k] = lit_neg( pStart[k] ); + RetValue = sat_solver_solve( p->pSatBmc, pStart + Beg, pStart + End, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + for ( k = Beg; k < End; k++ ) + pStart[k] = lit_neg( pStart[k] ); + + if ( RetValue != l_False ) + { + Beg = End; + Vec_IntWriteEntry( p->vCosts, i, -1 ); + Counter++; + continue; + } +/* + // add the clause + RetValue = sat_solver_addclause( p->pSatBmc, pStart + Beg, pStart + End ); + // assert( RetValue == 1 ); + if ( RetValue == 0 ) + { + printf( "Error: Solver is UNSAT after adding BMC clauses.\n" ); + return -1; + } +*/ + Beg = End; + + // simplify the solver + if ( p->pSatBmc->qtail != p->pSatBmc->qhead ) + { + RetValue = sat_solver_simplify(p->pSatBmc); + assert( RetValue != 0 ); + assert( p->pSatBmc->qtail == p->pSatBmc->qhead ); + } + } + // increment literals + for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) + p->vLits->pArray[i] += nLitsTot; + } + + // return clauses back to normal + nLitsTot = (p->nPref + p->nFrames) * nLitsTot; + for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) + p->vLits->pArray[i] -= nLitsTot; +/* + for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) + printf( "%d ", p->vLits->pArray[i] ); + printf( "\n" ); +*/ + return Counter; +} + +/**Function************************************************************* + + Synopsis [Cleans simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausSimInfoClean( Clu_Man_t * p ) +{ + assert( p->pCnf->nVars <= Vec_PtrSize(p->vCexes) ); + Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 ); + p->nCexes = 0; +} + +/**Function************************************************************* + + Synopsis [Reallocs simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausSimInfoRealloc( Clu_Man_t * p ) +{ + assert( p->nCexes == p->nCexesAlloc ); + Vec_PtrReallocSimInfo( p->vCexes ); + Vec_PtrCleanSimInfo( p->vCexes, p->nCexesAlloc/32, 2 * p->nCexesAlloc/32 ); + p->nCexesAlloc *= 2; +} + +/**Function************************************************************* + + Synopsis [Records simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausSimInfoRecord( Clu_Man_t * p, int * pModel ) +{ + int i; + if ( p->nCexes == p->nCexesAlloc ) + Fra_ClausSimInfoRealloc( p ); + assert( p->nCexes < p->nCexesAlloc ); + for ( i = 0; i < p->pCnf->nVars; i++ ) + { + if ( pModel[i] == l_True ) + { + assert( Aig_InfoHasBit( Vec_PtrEntry(p->vCexes, i), p->nCexes ) == 0 ); + Aig_InfoSetBit( Vec_PtrEntry(p->vCexes, i), p->nCexes ); + } + } + p->nCexes++; +} + +/**Function************************************************************* + + Synopsis [Uses the simulation info.] + + Description [Returns 1 if the simulation info disproved the clause.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausSimInfoCheck( Clu_Man_t * p, int * pLits, int nLits ) +{ + unsigned * pSims[16], uWord; + int nWords, iVar, i, w; + for ( i = 0; i < nLits; i++ ) + { + iVar = lit_var(pLits[i]) - p->nFrames * p->pCnf->nVars; + assert( iVar > 0 && iVar < p->pCnf->nVars ); + pSims[i] = Vec_PtrEntry( p->vCexes, iVar ); + } + nWords = p->nCexes / 32; + for ( w = 0; w < nWords; w++ ) + { + uWord = ~(unsigned)0; + for ( i = 0; i < nLits; i++ ) + uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]); + if ( uWord ) + return 1; + } + if ( p->nCexes % 32 ) + { + uWord = ~(unsigned)0; + for ( i = 0; i < nLits; i++ ) + uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]); + if ( uWord & Aig_InfoMask( p->nCexes % 32 ) ) + return 1; + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClausInductiveClauses( Clu_Man_t * p ) +{ +// Aig_Obj_t * pObjLi, * pObjLo; + int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f, fFlag;//, Lits[2]; + p->fFail = 0; + + // reset the solver + if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); + p->pSatMain = Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 ); + if ( p->pSatMain == NULL ) + { + printf( "Error: Main solver is unsat.\n" ); + return -1; + } + Fra_ClausSimInfoClean( p ); + +/* + // check if the property holds + if ( Fra_ClausRunSat0( p ) ) + printf( "Property holds without strengthening.\n" ); + else + printf( "Property does not hold without strengthening.\n" ); +*/ +/* + // add constant registers + Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) + if ( Aig_ObjFanin0(pObjLi) == Aig_ManConst1(p->pAig) ) + { + for ( k = 0; k < p->nFrames; k++ ) + { + Lits[0] = k * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObjLo->Id], Aig_ObjFaninC0(pObjLi) ); + RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 ); + if ( RetValue == 0 ) + { + printf( "Error: Solver is UNSAT after adding constant-register clauses.\n" ); + return -1; + } + } + } +*/ + + + // add the proven clauses + nLitsTot = 2 * p->pCnf->nVars; + pStart = Vec_IntArray(p->vLitsProven); + for ( f = 0; f < p->nFrames; f++ ) + { + Beg = 0; + Vec_IntForEachEntry( p->vClausesProven, End, i ) + { + assert( End - Beg <= p->nLutSize ); + // add the clause to all timeframes + RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); + if ( RetValue == 0 ) + { + printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); + return -1; + } + Beg = End; + } + // increment literals + for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ ) + p->vLitsProven->pArray[i] += nLitsTot; + } + // return clauses back to normal + nLitsTot = (p->nFrames) * nLitsTot; + for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ ) + p->vLitsProven->pArray[i] -= nLitsTot; + +/* + // add the proven clauses + nLitsTot = 2 * p->pCnf->nVars; + pStart = Vec_IntArray(p->vLitsProven); + Beg = 0; + Vec_IntForEachEntry( p->vClausesProven, End, i ) + { + assert( End - Beg <= p->nLutSize ); + // add the clause to all timeframes + RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); + if ( RetValue == 0 ) + { + printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); + return -1; + } + Beg = End; + } +*/ + + // add the clauses + nLitsTot = 2 * p->pCnf->nVars; + pStart = Vec_IntArray(p->vLits); + for ( f = 0; f < p->nFrames; f++ ) + { + Beg = 0; + Vec_IntForEachEntry( p->vClauses, End, i ) + { + if ( Vec_IntEntry( p->vCosts, i ) == -1 ) + { + Beg = End; + continue; + } + assert( Vec_IntEntry( p->vCosts, i ) > 0 ); + assert( End - Beg <= p->nLutSize ); + // add the clause to all timeframes + RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); + if ( RetValue == 0 ) + { + printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); + return -1; + } + Beg = End; + } + // increment literals + for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) + p->vLits->pArray[i] += nLitsTot; + } + + // simplify the solver + if ( p->pSatMain->qtail != p->pSatMain->qhead ) + { + RetValue = sat_solver_simplify(p->pSatMain); + assert( RetValue != 0 ); + assert( p->pSatMain->qtail == p->pSatMain->qhead ); + } + + // check if the property holds + if ( p->fTarget ) + { + if ( Fra_ClausRunSat0( p ) ) + { + if ( p->fVerbose ) + printf( " Property holds. " ); + } + else + { + if ( p->fVerbose ) + printf( " Property fails. " ); + // return -2; + p->fFail = 1; + } + } + +/* + // add the property for the first K frames + for ( i = 0; i < p->nFrames; i++ ) + { + Aig_Obj_t * pObj; + int Lits[2]; + // set the output literals + pObj = Aig_ManPo(p->pAig, 0); + Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 1 ); + // add the clause + RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 ); +// assert( RetValue == 1 ); + if ( RetValue == 0 ) + { + printf( "Error: Solver is UNSAT after adding property for the first K frames.\n" ); + return -1; + } + } +*/ + + // simplify the solver + if ( p->pSatMain->qtail != p->pSatMain->qhead ) + { + RetValue = sat_solver_simplify(p->pSatMain); + assert( RetValue != 0 ); + assert( p->pSatMain->qtail == p->pSatMain->qhead ); + } + + + // check the clause in the last timeframe + Beg = 0; + Counter = 0; + Vec_IntForEachEntry( p->vClauses, End, i ) + { + if ( Vec_IntEntry( p->vCosts, i ) == -1 ) + { + Beg = End; + continue; + } + assert( Vec_IntEntry( p->vCosts, i ) > 0 ); + assert( End - Beg <= p->nLutSize ); + + if ( Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg) ) + { + fFlag = 1; +// printf( "s-" ); + + Beg = End; + Vec_IntWriteEntry( p->vCosts, i, -1 ); + Counter++; + continue; + } + else + { + fFlag = 0; +// printf( "s?" ); + } + + for ( k = Beg; k < End; k++ ) + pStart[k] = lit_neg( pStart[k] ); + RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + for ( k = Beg; k < End; k++ ) + pStart[k] = lit_neg( pStart[k] ); + + // the problem is not solved + if ( RetValue != l_False ) + { +// printf( "S- " ); + Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model.ptr + p->nFrames * p->pCnf->nVars ); +// RetValue = Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg); +// assert( RetValue ); + + Beg = End; + Vec_IntWriteEntry( p->vCosts, i, -1 ); + Counter++; + continue; + } +// printf( "S+ " ); +// assert( !fFlag ); + +/* + // add the clause + RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); +// assert( RetValue == 1 ); + if ( RetValue == 0 ) + { + printf( "Error: Solver is UNSAT after adding proved clauses.\n" ); + return -1; + } +*/ + Beg = End; + + // simplify the solver + if ( p->pSatMain->qtail != p->pSatMain->qhead ) + { + RetValue = sat_solver_simplify(p->pSatMain); + assert( RetValue != 0 ); + assert( p->pSatMain->qtail == p->pSatMain->qhead ); + } + } + + // return clauses back to normal + nLitsTot = p->nFrames * nLitsTot; + for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) + p->vLits->pArray[i] -= nLitsTot; + +// if ( fFail ) +// return -2; + return Counter; +} + + + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Clu_Man_t * Fra_ClausAlloc( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fTarget, int fVerbose, int fVeryVerbose ) +{ + Clu_Man_t * p; + p = ALLOC( Clu_Man_t, 1 ); + memset( p, 0, sizeof(Clu_Man_t) ); + p->pAig = pAig; + p->nFrames = nFrames; + p->nPref = nPref; + p->nClausesMax = nClausesMax; + p->nLutSize = nLutSize; + p->nLevels = nLevels; + p->nCutsMax = nCutsMax; + p->nBatches = nBatches; + p->fStepUp = fStepUp; + p->fTarget = fTarget; + p->fVerbose = fVerbose; + p->fVeryVerbose = fVeryVerbose; + p->nSimWords = 512;//1024;//64; + p->nSimFrames = 32;//8;//32; + p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames; + + p->vLits = Vec_IntAlloc( 1<<14 ); + p->vClauses = Vec_IntAlloc( 1<<12 ); + p->vCosts = Vec_IntAlloc( 1<<12 ); + + p->vLitsProven = Vec_IntAlloc( 1<<14 ); + p->vClausesProven= Vec_IntAlloc( 1<<12 ); + + p->nCexesAlloc = 1024; + p->vCexes = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pAig)+1, p->nCexesAlloc/32 ); + Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausFree( Clu_Man_t * p ) +{ + if ( p->vCexes ) Vec_PtrFree( p->vCexes ); + if ( p->vLits ) Vec_IntFree( p->vLits ); + if ( p->vClauses ) Vec_IntFree( p->vClauses ); + if ( p->vLitsProven ) Vec_IntFree( p->vLitsProven ); + if ( p->vClausesProven ) Vec_IntFree( p->vClausesProven ); + if ( p->vCosts ) Vec_IntFree( p->vCosts ); + if ( p->pCnf ) Cnf_DataFree( p->pCnf ); + if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); + if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausAddToStorage( Clu_Man_t * p ) +{ + int * pStart; + int Beg, End, Counter, i, k; + Beg = 0; + Counter = 0; + pStart = Vec_IntArray( p->vLits ); + Vec_IntForEachEntry( p->vClauses, End, i ) + { + if ( Vec_IntEntry( p->vCosts, i ) == -1 ) + { + Beg = End; + continue; + } + assert( Vec_IntEntry( p->vCosts, i ) > 0 ); + assert( End - Beg <= p->nLutSize ); + for ( k = Beg; k < End; k++ ) + Vec_IntPush( p->vLitsProven, pStart[k] ); + Vec_IntPush( p->vClausesProven, Vec_IntSize(p->vLitsProven) ); + Beg = End; + Counter++; + + if ( i < p->nOneHots ) + p->nOneHotsProven++; + } + if ( p->fVerbose ) + printf( "Added to storage %d proved clauses (including %d one-hot clauses)\n", Counter, p->nOneHotsProven ); + + Vec_IntClear( p->vClauses ); + Vec_IntClear( p->vLits ); + Vec_IntClear( p->vCosts ); + p->nClauses = 0; + + p->fNothingNew = (int)(Counter == 0); +} + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausPrintIndClauses( Clu_Man_t * p ) +{ + int Counters[9] = {0}; + int * pStart; + int Beg, End, i; + Beg = 0; + pStart = Vec_IntArray( p->vLitsProven ); + Vec_IntForEachEntry( p->vClausesProven, End, i ) + { + if ( End - Beg >= 8 ) + Counters[8]++; + else + Counters[End - Beg]++; +//printf( "%d ", End-Beg ); + Beg = End; + } + printf( "SUMMARY: Total proved clauses = %d. ", Vec_IntSize(p->vClausesProven) ); + printf( "Clause per lit: " ); + for ( i = 0; i < 8; i++ ) + if ( Counters[i] ) + printf( "%d=%d ", i, Counters[i] ); + if ( Counters[8] ) + printf( ">7=%d ", Counters[8] ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Checks if the clause holds using the given simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausEstimateCoverageOne( Fra_Sml_t * pSim, int * pLits, int nLits, int * pVar2Id, unsigned * pResult ) +{ + unsigned * pSims[16]; + int iVar, i, w; + for ( i = 0; i < nLits; i++ ) + { + iVar = lit_var(pLits[i]); + pSims[i] = Fra_ObjSim( pSim, pVar2Id[iVar] ); + } + for ( w = 0; w < pSim->nWordsTotal; w++ ) + { + pResult[w] = ~(unsigned)0; + for ( i = 0; i < nLits; i++ ) + pResult[w] &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]); + } +} + +/**Function************************************************************* + + Synopsis [Estimates the coverage of state space by clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausEstimateCoverage( Clu_Man_t * p ) +{ + int nCombSimWords = (1<<11); + Fra_Sml_t * pComb; + unsigned * pResultTot, * pResultOne; + int nCovered, Beg, End, i, w; + int * pStart, * pVar2Id; + int clk = clock(); + // simulate the circuit with nCombSimWords * 32 = 64K patterns + srand( 0xAABBAABB ); + pComb = Fra_SmlSimulateComb( p->pAig, nCombSimWords ); + // create mapping from SAT vars to node IDs + pVar2Id = ALLOC( int, p->pCnf->nVars ); + memset( pVar2Id, 0, sizeof(int) * p->pCnf->nVars ); + for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) + if ( p->pCnf->pVarNums[i] >= 0 ) + { + assert( p->pCnf->pVarNums[i] < p->pCnf->nVars ); + pVar2Id[ p->pCnf->pVarNums[i] ] = i; + } + // get storage for one assignment and all assignments + assert( Aig_ManPoNum(p->pAig) > 2 ); + pResultOne = Fra_ObjSim( pComb, Aig_ManPo(p->pAig, 0)->Id ); + pResultTot = Fra_ObjSim( pComb, Aig_ManPo(p->pAig, 1)->Id ); + // start the OR of don't-cares + for ( w = 0; w < nCombSimWords; w++ ) + pResultTot[w] = 0; + // check clauses + Beg = 0; + pStart = Vec_IntArray( p->vLitsProven ); + Vec_IntForEachEntry( p->vClausesProven, End, i ) + { + Fra_ClausEstimateCoverageOne( pComb, pStart + Beg, End-Beg, pVar2Id, pResultOne ); + Beg = End; + for ( w = 0; w < nCombSimWords; w++ ) + pResultTot[w] |= pResultOne[w]; + } + // count the total number of patterns contained in the don't-care + nCovered = 0; + for ( w = 0; w < nCombSimWords; w++ ) + nCovered += Aig_WordCountOnes( pResultTot[w] ); + Fra_SmlStop( pComb ); + free( pVar2Id ); + // print the result + printf( "Care states ratio = %f. ", 1.0 * (nCombSimWords * 32 - nCovered) / (nCombSimWords * 32) ); + printf( "(%d out of %d patterns) ", nCombSimWords * 32 - nCovered, nCombSimWords * 32 ); + PRT( "Time", clock() - clk ); +} + + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose ) +{ + Clu_Man_t * p; + int clk, clkTotal = clock(), clkInd; + int b, Iter, Counter, nPrefOld; + int nClausesBeg = 0; + + // create the manager + p = Fra_ClausAlloc( pAig, nFrames, nPref, nClausesMax, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fTarget, fVerbose, fVeryVerbose ); +if ( p->fVerbose ) +{ + printf( "PARAMETERS: Frames = %d. Pref = %d. Clauses max = %d. Cut size = %d.\n", nFrames, nPref, nClausesMax, nLutSize ); + printf( "Level max = %d. Cuts max = %d. Batches = %d. Increment cut size = %s.\n", nLevels, nCutsMax, nBatches, fStepUp? "yes":"no" ); +//PRT( "Sim-seq", clock() - clk ); +} + + assert( !p->fTarget || Aig_ManPoNum(pAig) - Aig_ManRegNum(pAig) == 1 ); + +clk = clock(); + // derive CNF + if ( p->fTarget ) + p->pAig->nRegs++; + p->pCnf = Cnf_DeriveSimple( p->pAig, Aig_ManPoNum(p->pAig) ); + if ( p->fTarget ) + p->pAig->nRegs--; +if ( fVerbose ) +{ +//PRT( "CNF ", clock() - clk ); +} + + // check BMC +clk = clock(); + p->pSatBmc = Cnf_DataWriteIntoSolver( p->pCnf, p->nPref + p->nFrames, 1 ); + if ( p->pSatBmc == NULL ) + { + printf( "Error: BMC solver is unsat.\n" ); + Fra_ClausFree( p ); + return 1; + } + if ( p->fTarget && !Fra_ClausRunBmc( p ) ) + { + printf( "Problem fails the base case after %d frame expansion.\n", p->nPref + p->nFrames ); + Fra_ClausFree( p ); + return 1; + } +if ( fVerbose ) +{ +//PRT( "SAT-bmc", clock() - clk ); +} + + // start the SAT solver +clk = clock(); + p->pSatMain = Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 ); + if ( p->pSatMain == NULL ) + { + printf( "Error: Main solver is unsat.\n" ); + Fra_ClausFree( p ); + return 1; + } + + + for ( b = 0; b < p->nBatches; b++ ) + { +// if ( fVerbose ) + printf( "*** BATCH %d: ", b+1 ); + if ( b && p->nLutSize < 12 && (!p->fFiltering || p->fNothingNew || p->fStepUp) ) + p->nLutSize++; + printf( "Using %d-cuts.\n", p->nLutSize ); + + // try solving without additional clauses + if ( p->fTarget && Fra_ClausRunSat( p ) ) + { + printf( "Problem is inductive without strengthening.\n" ); + Fra_ClausFree( p ); + return 1; + } + if ( fVerbose ) + { +// PRT( "SAT-ind", clock() - clk ); + } + + // collect the candidate inductive clauses using 4-cuts + clk = clock(); + nPrefOld = p->nPref; p->nPref = 0; p->nSimWordsPref = 0; + // Fra_ClausProcessClauses( p, fRefs ); + Fra_ClausProcessClauses2( p, fRefs ); + p->nPref = nPrefOld; + p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames; + nClausesBeg = p->nClauses; + + //PRT( "Clauses", clock() - clk ); + + + // check clauses using BMC + if ( fBmc ) + { + clk = clock(); + Counter = Fra_ClausBmcClauses( p ); + p->nClauses -= Counter; + if ( fVerbose ) + { + printf( "BMC disproved %d clauses. ", Counter ); + PRT( "Time", clock() - clk ); + } + } + + + // prove clauses inductively + clkInd = clk = clock(); + Counter = 1; + for ( Iter = 0; Counter > 0; Iter++ ) + { + if ( fVerbose ) + printf( "Iter %3d : Begin = %5d. ", Iter, p->nClauses ); + Counter = Fra_ClausInductiveClauses( p ); + if ( Counter > 0 ) + p->nClauses -= Counter; + if ( fVerbose ) + { + printf( "End = %5d. Exs = %5d. ", p->nClauses, p->nCexes ); + // printf( "\n" ); + PRT( "Time", clock() - clk ); + } + clk = clock(); + } + if ( p->fTarget ) + { + if ( Counter == -1 ) + printf( "Fra_Claus(): Internal error. " ); + else if ( p->fFail ) + printf( "Property FAILS during refinement. " ); + else + printf( "Property HOLDS inductively after strengthening. " ); + PRT( "Time ", clock() - clkTotal ); + if ( !p->fFail ) + break; + } + else + { + printf( "Finished proving inductive clauses. " ); + PRT( "Time ", clock() - clkTotal ); + } + + // add proved clauses to storage + Fra_ClausAddToStorage( p ); + } + + if ( !p->fTarget && p->fVerbose ) + { + Fra_ClausPrintIndClauses( p ); + Fra_ClausEstimateCoverage( p ); + } +/* + // print the statistic into a file + { + FILE * pTable; + assert( p->nBatches == 1 ); + pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%s ", pAig->pName ); + fprintf( pTable, "%d ", Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig) ); + fprintf( pTable, "%d ", Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig) ); + fprintf( pTable, "%d ", Aig_ManRegNum(pAig) ); + fprintf( pTable, "%d ", Aig_ManNodeNum(pAig) ); + fprintf( pTable, "%d ", p->nCuts ); + fprintf( pTable, "%d ", nClausesBeg ); + fprintf( pTable, "%d ", p->nClauses ); + fprintf( pTable, "%d ", Iter ); + fprintf( pTable, "%.2f ", (float)(clkInd-clkTotal)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "%.2f ", (float)(clock()-clkInd)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "%.2f ", (float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + // clean the manager + Fra_ClausFree( p ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/fra/fraCnf.c b/src/abc8/fra/fraCnf.c new file mode 100644 index 00000000..d96fe8a1 --- /dev/null +++ b/src/abc8/fra/fraCnf.c @@ -0,0 +1,284 @@ +/**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 ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Fra_ObjSatNum(pObj) ) + return; + assert( Fra_ObjSatNum(pObj) == 0 ); + assert( Fra_ObjFaninVec(pObj) == NULL ); + if ( Aig_ObjIsConst1(pObj) ) + return; + 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/abc8/fra/fraCore.c b/src/abc8/fra/fraCore.c new file mode 100644 index 00000000..95d65e25 --- /dev/null +++ b/src/abc8/fra/fraCore.c @@ -0,0 +1,466 @@ +/**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, * pChild; + int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; + if ( p->pData ) + return 0; + Aig_ManForEachPoSeq( p, pObj, i ) + { + pChild = Aig_ObjChild0(pObj); + // check if the output is constant 0 + if ( pChild == Aig_ManConst0(p) ) + { + CountConst0++; + continue; + } + // check if the output is constant 1 + if ( pChild == Aig_ManConst1(p) ) + { + CountNonConst0++; + continue; + } + // check if the output can be not constant 0 + if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) + { + 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 [Reports the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigMiterAssertedOutput( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pChild; + int i; + Aig_ManForEachPoSeq( p, pObj, i ) + { + pChild = Aig_ObjChild0(pObj); + // check if the output is constant 0 + if ( pChild == Aig_ManConst0(p) ) + continue; + // check if the output is constant 1 + if ( pChild == Aig_ManConst1(p) ) + return i; + // check if the output can be not constant 0 + if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) + return i; + } + 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->pManFraig->pData ) + return; + 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 = NULL; + Aig_Obj_t * pObj, * pObjNew; + int i, 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 +// if ( !p->pPars->fDontShowBar ) +// pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pManAig) ); + Aig_ManForEachNode( p->pManAig, pObj, i ) + { +// if ( pProgress ) +// 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 ); + } +// if ( pProgress ) +// 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; + pPars->fDontShowBar = 1; + return Fra_FraigPerform( pManAig, pPars ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve ) +{ + 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 = fProve; + pPars->fVerbose = 0; + pPars->fDontShowBar = 1; + pFraig = Fra_FraigPerform( pManAig, pPars ); + return pFraig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/fra/fraImp.c b/src/abc8/fra/fraImp.c new file mode 100644 index 00000000..e2bee834 --- /dev/null +++ b/src/abc8/fra/fraImp.c @@ -0,0 +1,723 @@ +/**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-- ) + { + // HERE WE ARE MISSING SOME POTENTIAL IMPLICATIONS (with complement!) + + 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/abc8/fra/fraInd.c b/src/abc8/fra/fraInd.c new file mode 100644 index 00000000..1c2140bb --- /dev/null +++ b/src/abc8/fra/fraInd.c @@ -0,0 +1,484 @@ +/**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 = Dar_ManRwsat( pTemp, 1, 0 ); + pTemp = Dar_ManRewriteDefault( p->pManFraig ); +// 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 nMaxLevs, 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->nMaxLevs = nMaxLevs; + 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, p->pPars->nMaxLevs ); +// 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, 1, 0 ); + 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. ", Aig_ManNodeNum(p->pManFraig) ); + printf( "\n" ); + } + + // perform sweeping + p->nSatCallsRecent = 0; + p->nSatCallsSkipped = 0; +clk2 = clock(); + Fra_FraigSweep( p ); + if ( fVerbose ) + { +// PRT( "t", clock() - clk2 ); + } + +// 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/abc8/fra/fraLcr.c b/src/abc8/fra/fraLcr.c new file mode 100644 index 00000000..a6460ed7 --- /dev/null +++ b/src/abc8/fra/fraLcr.c @@ -0,0 +1,656 @@ +/**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 ) + Aig_ManForEachObj( 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[(long)pObj0->pNext]; + nPart1 = pLcr->pInToOutPart[(long)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[(long)pObj0->pNext] ); + pOut1 = Aig_ManPo( pFraig, pLcr->pInToOutNum[(long)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[(long)pObj->pNext]; + pFraig = Vec_PtrEntry( pLcr->vFraigs, nPart ); + // get the fraig outputs + pOut = Aig_ManPo( pFraig, pLcr->pInToOutNum[(long)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 *)(long)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+(long)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+(long)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[(long)ppClass[c]->pNext] = i; + pInToOutNum[(long)ppClass[c]->pNext] = Vec_IntSize(vOneNew); + Vec_IntPush( vOneNew, Offset+(long)ppClass[c]->pNext ); + } + } + else + { + pObjPi = Vec_PtrEntry( pCla->vClasses1, Out - Vec_PtrSize(pCla->vClasses) ); + pInToOutPart[(long)pObjPi->pNext] = i; + pInToOutNum[(long)pObjPi->pNext] = Vec_IntSize(vOneNew); + Vec_IntPush( vOneNew, Offset+(long)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+(long)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+(long)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+(long)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+(long)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; + 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 ) + { + pAig->pSeqModel = Fra_SmlGetCounterExample( pSml ); + 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, 0 ); + 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, 0 ); +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/abc8/fra/fraMan.c b/src/abc8/fra/fraMan.c new file mode 100644 index 00000000..f505b0c2 --- /dev/null +++ b/src/abc8/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/src/abc8/fra/fraPart.c b/src/abc8/fra/fraPart.c new file mode 100644 index 00000000..f4964746 --- /dev/null +++ b/src/abc8/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/src/abc8/fra/fraSat.c b/src/abc8/fra/fraSat.c new file mode 100644 index 00000000..819605d6 --- /dev/null +++ b/src/abc8/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/src/abc8/fra/fraSec.c b/src/abc8/fra/fraSec.c new file mode 100644 index 00000000..c6bdc20e --- /dev/null +++ b/src/abc8/fra/fraSec.c @@ -0,0 +1,290 @@ +/**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, 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, 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 ); + p->pSeqModel = pTemp->pSeqModel; pTemp->pSeqModel = NULL; + 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, 0 ); + 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, 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( pTemp = pNew ); + Aig_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Rewriting: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + + // perform retiming +// if ( fRetimeFirst && pNew->nRegs ) + 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 + if ( pNew->nRegs ) + { +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 ) + { + p->pSeqModel = Fra_SmlGetCounterExample( pSml ); + 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, 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/abc8/fra/fraSim.c b/src/abc8/fra/fraSim.c new file mode 100644 index 00000000..1ad2d4f7 --- /dev/null +++ b/src/abc8/fra/fraSim.c @@ -0,0 +1,1066 @@ +/**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 * pObjPo ) +{ + Aig_Obj_t * pFanin, * pObjPi; + unsigned * pSims; + int i, k, BestPat, * pModel; + // find the word of the pattern + pFanin = Aig_ObjFanin0(pObjPo); + pSims = Fra_ObjSim(p->pSml, pFanin->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)+1 ); + Aig_ManForEachPi( p->pManAig, pObjPi, i ) + { + pModel[i] = Aig_InfoHasBit(Fra_ObjSim(p->pSml, pObjPi->Id), BestPat); +// printf( "%d", pModel[i] ); + } + pModel[Aig_ManPiNum(p->pManAig)] = pObjPo->Id; +// 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, 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 ); + if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) + return; + Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, 0 ); +// 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; +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlRunCounterExample( Aig_Man_t * pAig, Fra_Cex_t * p ) +{ + Fra_Sml_t * pSml; + Aig_Obj_t * pObj; + int RetValue, i, k, iBit; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManRegNum(pAig) < Aig_ManPiNum(pAig) ); + // start a new sequential simulator + pSml = Fra_SmlStart( pAig, 0, p->iFrame+1, 1 ); + // assign simulation info for the registers + iBit = 0; + Aig_ManForEachLoSeq( pAig, pObj, i ) + Fra_SmlAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), 0 ); + // assign simulation info for the primary inputs + for ( i = 0; i <= p->iFrame; i++ ) + Aig_ManForEachPiSeq( pAig, pObj, k ) + Fra_SmlAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), i ); + assert( iBit == p->nBits ); + // run random simulation + Fra_SmlSimulateOne( pSml ); + // check if the given output has failed + RetValue = !Fra_SmlNodeIsZero( pSml, Aig_ManPo(pAig, p->iPo) ); + Fra_SmlStop( pSml ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Allocates a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Cex_t * Fra_SmlAllocCounterExample( int nRegs, int nRealPis, int nFrames ) +{ + Fra_Cex_t * pCex; + int nWords = Aig_BitWordNum( nRegs + nRealPis * nFrames ); + pCex = (Fra_Cex_t *)malloc( sizeof(Fra_Cex_t) + sizeof(unsigned) * nWords ); + memset( pCex, 0, sizeof(Fra_Cex_t) + sizeof(unsigned) * nWords ); + pCex->nRegs = nRegs; + pCex->nPis = nRealPis; + pCex->nBits = nRegs + nRealPis * nFrames; + return pCex; +} + +/**Function************************************************************* + + Synopsis [Frees the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlFreeCounterExample( Fra_Cex_t * pCex ) +{ + free( pCex ); +} + +/**Function************************************************************* + + Synopsis [Creates sequential counter-example from the simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ) +{ + Fra_Cex_t * pCex; + Aig_Obj_t * pObj; + unsigned * pSims; + int iPo, iFrame, iBit, i, k; + + // make sure the simulation manager has it + assert( p->fNonConstOut ); + + // find the first output that failed + iPo = -1; + iBit = -1; + iFrame = -1; + Aig_ManForEachPoSeq( p->pAig, pObj, iPo ) + { + if ( Fra_SmlNodeIsZero(p, pObj) ) + continue; + pSims = Fra_ObjSim( p, pObj->Id ); + for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) + if ( pSims[i] ) + { + iFrame = i / p->nWordsFrame; + iBit = 32 * (i % p->nWordsFrame) + Aig_WordFindFirstBit( pSims[i] ); + break; + } + break; + } + assert( iPo < Aig_ManPoNum(p->pAig)-Aig_ManRegNum(p->pAig) ); + assert( iFrame < p->nFrames ); + assert( iBit < 32 * p->nWordsFrame ); + + // allocate the counter example + pCex = Fra_SmlAllocCounterExample( Aig_ManRegNum(p->pAig), Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 ); + pCex->iPo = iPo; + pCex->iFrame = iFrame; + + // copy the bit data + Aig_ManForEachLoSeq( p->pAig, pObj, k ) + { + pSims = Fra_ObjSim( p, pObj->Id ); + if ( Aig_InfoHasBit( pSims, iBit ) ) + Aig_InfoSetBit( pCex->pData, k ); + } + for ( i = 0; i <= iFrame; i++ ) + { + Aig_ManForEachPiSeq( p->pAig, pObj, k ) + { + pSims = Fra_ObjSim( p, pObj->Id ); + if ( Aig_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) ) + Aig_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k ); + } + } + // verify the counter example + if ( !Fra_SmlRunCounterExample( p->pAig, pCex ) ) + { + printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); + Fra_SmlFreeCounterExample( pCex ); + pCex = NULL; + } + return pCex; +} + +/**Function************************************************************* + + Synopsis [Generates seq counter-example from the combinational one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ) +{ + Fra_Cex_t * pCex; + Aig_Obj_t * pObj; + int i, nFrames, nTruePis, nTruePos, iPo, iFrame; + // get the number of frames + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManRegNum(pFrames) == 0 ); + nTruePis = Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig); + nTruePos = Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig); + nFrames = Aig_ManPiNum(pFrames) / nTruePis; + assert( nTruePis * nFrames == Aig_ManPiNum(pFrames) ); + assert( nTruePos * nFrames == Aig_ManPoNum(pFrames) ); + // find the PO that failed + iPo = -1; + iFrame = -1; + Aig_ManForEachPo( pFrames, pObj, i ) + if ( pObj->Id == pModel[Aig_ManPiNum(pFrames)] ) + { + iPo = i % nTruePos; + iFrame = i / nTruePos; + break; + } + assert( iPo >= 0 ); + // allocate the counter example + pCex = Fra_SmlAllocCounterExample( Aig_ManRegNum(pAig), nTruePis, iFrame + 1 ); + pCex->iPo = iPo; + pCex->iFrame = iFrame; + + // copy the bit data + for ( i = 0; i < Aig_ManPiNum(pFrames); i++ ) + { + if ( pModel[i] ) + Aig_InfoSetBit( pCex->pData, pCex->nRegs + i ); + if ( pCex->nRegs + i == pCex->nBits - 1 ) + break; + } + + // verify the counter example + if ( !Fra_SmlRunCounterExample( pAig, pCex ) ) + { + printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); + Fra_SmlFreeCounterExample( pCex ); + pCex = NULL; + } + return pCex; + +} + +/**Function************************************************************* + + Synopsis [Make the trivial counter-example for the trivially asserted output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Cex_t * Fra_SmlTrivCounterExample( Aig_Man_t * pAig, int iFrameOut ) +{ + Fra_Cex_t * pCex; + int nTruePis, nTruePos, iPo, iFrame; + assert( Aig_ManRegNum(pAig) > 0 ); + nTruePis = Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig); + nTruePos = Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig); + iPo = iFrameOut % nTruePos; + iFrame = iFrameOut / nTruePos; + // allocate the counter example + pCex = Fra_SmlAllocCounterExample( Aig_ManRegNum(pAig), nTruePis, iFrame + 1 ); + pCex->iPo = iPo; + pCex->iFrame = iFrame; + return pCex; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/fra/fra_.c b/src/abc8/fra/fra_.c new file mode 100644 index 00000000..2b601587 --- /dev/null +++ b/src/abc8/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/src/abc8/fra/module.make b/src/abc8/fra/module.make new file mode 100644 index 00000000..ffaca75c --- /dev/null +++ b/src/abc8/fra/module.make @@ -0,0 +1,15 @@ +SRC += src/aig/fra/fraBmc.c \ + src/aig/fra/fraCec.c \ + src/aig/fra/fraClass.c \ + src/aig/fra/fraClau.c \ + src/aig/fra/fraClaus.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/fraPart.c \ + src/aig/fra/fraSat.c \ + src/aig/fra/fraSec.c \ + src/aig/fra/fraSim.c diff --git a/src/abc8/ioa/ioa.h b/src/abc8/ioa/ioa.h new file mode 100644 index 00000000..2d7499cd --- /dev/null +++ b/src/abc8/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 "vec2.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, int fCompact ); +/*=== 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/abc8/ioa/ioaReadAig.c b/src/abc8/ioa/ioaReadAig.c new file mode 100644 index 00000000..498cdd30 --- /dev/null +++ b/src/abc8/ioa/ioaReadAig.c @@ -0,0 +1,366 @@ +/**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 /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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)); +} + +/**Function************************************************************* + + Synopsis [Decodes the encoded array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries ) +{ + Vec_Int_t * vLits; + int Lit, LitPrev, Diff, i; + vLits = Vec_IntAlloc( nEntries ); + LitPrev = Ioa_ReadAigerDecode( ppPos ); + Vec_IntPush( vLits, LitPrev ); + for ( i = 1; i < nEntries; i++ ) + { +// Diff = Lit - LitPrev; +// Diff = (Lit < LitPrev)? -Diff : Diff; +// Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev); + Diff = Ioa_ReadAigerDecode( ppPos ); + Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1; + Lit = Diff + LitPrev; + Vec_IntPush( vLits, Lit ); + LitPrev = Lit; + } + return vLits; +} + + +/**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_Int_t * vLits = NULL; + 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 || (pContents[3] != ' ' && pContents[3] != '2') ) + { + 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; + if ( pContents[3] == ' ' ) // standard AIGER + { + // scroll to the beginning of the binary data + for ( i = 0; i < nLatches + nOutputs; ) + if ( *pCur++ == '\n' ) + i++; + } + else // modified AIGER + { + vLits = Ioa_WriteDecodeLiterals( &pCur, nLatches + nOutputs ); + } + + // 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 ); + if ( pContents[3] == ' ' ) // standard AIGER + { + pCur = pDrivers; + for ( i = 0; i < nLatches; i++ ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Vec_PtrPush( vDrivers, pNode0 ); + } + // read the PO driver literals + for ( i = 0; i < nOutputs; i++ ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Vec_PtrPush( vDrivers, pNode0 ); + } + + } + else + { + // read the latch driver literals + for ( i = 0; i < nLatches; i++ ) + { + uLit0 = Vec_IntEntry( vLits, i ); + pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Vec_PtrPush( vDrivers, pNode0 ); + } + // read the PO driver literals + for ( i = 0; i < nOutputs; i++ ) + { + uLit0 = Vec_IntEntry( vLits, i+nLatches ); + pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Vec_PtrPush( vDrivers, pNode0 ); + } + Vec_IntFree( vLits ); + } + + // 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; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/ioa/ioaUtil.c b/src/abc8/ioa/ioaUtil.c new file mode 100644 index 00000000..79dcca1e --- /dev/null +++ b/src/abc8/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/src/abc8/ioa/ioaWriteAig.c b/src/abc8/ioa/ioaWriteAig.c new file mode 100644 index 00000000..166dca4b --- /dev/null +++ b/src/abc8/ioa/ioaWriteAig.c @@ -0,0 +1,378 @@ +/**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 int Ioa_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } +static int Ioa_ObjAigerNum( Aig_Obj_t * pObj ) { return pObj->iData; } +static void Ioa_ObjSetAigerNum( Aig_Obj_t * pObj, unsigned Num ) { pObj->iData = Num; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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; +} + +/**Function************************************************************* + + Synopsis [Create the array of literals to be written.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ioa_WriteAigerLiterals( Aig_Man_t * pMan ) +{ + Vec_Int_t * vLits; + Aig_Obj_t * pObj, * pDriver; + int i; + vLits = Vec_IntAlloc( Aig_ManPoNum(pMan) ); + Aig_ManForEachLiSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); + } + Aig_ManForEachPoSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); + } + return vLits; +} + +/**Function************************************************************* + + Synopsis [Creates the binary encoded array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Ioa_WriteEncodeLiterals( Vec_Int_t * vLits ) +{ + Vec_Str_t * vBinary; + int Pos = 0, Lit, LitPrev, Diff, i; + vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) ); + LitPrev = Vec_IntEntry( vLits, 0 ); + Pos = Ioa_WriteAigerEncode( Vec_StrArray(vBinary), Pos, LitPrev ); + Vec_IntForEachEntryStart( vLits, Lit, i, 1 ) + { + Diff = Lit - LitPrev; + Diff = (Lit < LitPrev)? -Diff : Diff; + Diff = (Diff << 1) | (int)(Lit < LitPrev); + Pos = Ioa_WriteAigerEncode( Vec_StrArray(vBinary), Pos, Diff ); + LitPrev = Lit; + if ( Pos + 10 > vBinary->nCap ) + Vec_StrGrow( vBinary, vBinary->nCap+1 ); + } + vBinary->nSize = Pos; +/* + // verify + { + extern Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries ); + char * pPos = Vec_StrArray( vBinary ); + Vec_Int_t * vTemp = Ioa_WriteDecodeLiterals( &pPos, Vec_IntSize(vLits) ); + for ( i = 0; i < Vec_IntSize(vLits); i++ ) + { + int Entry1 = Vec_IntEntry(vLits,i); + int Entry2 = Vec_IntEntry(vTemp,i); + assert( Entry1 == Entry2 ); + } + Vec_IntFree( vTemp ); + } +*/ + return vBinary; +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ) +{ +// 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%s %u %u %u %u %u\n", + fCompact? "2" : "", + 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 + + if ( !fCompact ) + { + // 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) ) ); + } + } + else + { + Vec_Int_t * vLits = Ioa_WriteAigerLiterals( pMan ); + Vec_Str_t * vBinary = Ioa_WriteEncodeLiterals( vLits ); + fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); + Vec_StrFree( vBinary ); + Vec_IntFree( vLits ); + } + + // write the nodes into the buffer + Pos = 0; + nBufferSize = 6 * Aig_ManNodeNum(pMan) + 100; // skeptically assuming 3 chars per one AIG edge + pBuffer = ALLOC( unsigned 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, (unsigned)(uLit - uLit1) ); + Pos = Ioa_WriteAigerEncode( pBuffer, Pos, (unsigned)(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 on %s\n", Ioa_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/abc8/ioa/module.make b/src/abc8/ioa/module.make new file mode 100644 index 00000000..66b4a0d5 --- /dev/null +++ b/src/abc8/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/src/abc8/kit/cloud.c b/src/abc8/kit/cloud.c new file mode 100644 index 00000000..6e6691f0 --- /dev/null +++ b/src/abc8/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/src/abc8/kit/cloud.h b/src/abc8/kit/cloud.h new file mode 100644 index 00000000..ac9d45f4 --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kit.h b/src/abc8/kit/kit.h new file mode 100644 index 00000000..2a19a5ac --- /dev/null +++ b/src/abc8/kit/kit.h @@ -0,0 +1,596 @@ +/**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 "vec2.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/abc8/kit/kitAig.c b/src/abc8/kit/kitAig.c new file mode 100644 index 00000000..83012a8c --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kitBdd.c b/src/abc8/kit/kitBdd.c new file mode 100644 index 00000000..9c8d4f7a --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kitCloud.c b/src/abc8/kit/kitCloud.c new file mode 100644 index 00000000..7b160fea --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kitFactor.c b/src/abc8/kit/kitFactor.c new file mode 100644 index 00000000..f596d9a8 --- /dev/null +++ b/src/abc8/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 division 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/src/abc8/kit/kitGraph.c b/src/abc8/kit/kitGraph.c new file mode 100644 index 00000000..80dcbdc0 --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kitHop.c b/src/abc8/kit/kitHop.c new file mode 100644 index 00000000..86ec5a88 --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kitIsop.c b/src/abc8/kit/kitIsop.c new file mode 100644 index 00000000..42fae2ea --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kitSop.c b/src/abc8/kit/kitSop.c new file mode 100644 index 00000000..20ad0651 --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kitTruth.c b/src/abc8/kit/kitTruth.c new file mode 100644 index 00000000..dab60132 --- /dev/null +++ b/src/abc8/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/src/abc8/kit/kit_.c b/src/abc8/kit/kit_.c new file mode 100644 index 00000000..5c68ee3c --- /dev/null +++ b/src/abc8/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/src/abc8/kit/module.make b/src/abc8/kit/module.make new file mode 100644 index 00000000..3df3aa1c --- /dev/null +++ b/src/abc8/kit/module.make @@ -0,0 +1,8 @@ +SRC += src/aig/kit/kitAig.c \ + src/aig/kit/kitCloud.c src/aig/kit/cloud.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/abc8/vec2/module.make b/src/abc8/vec2/module.make new file mode 100644 index 00000000..d6d908e7 --- /dev/null +++ b/src/abc8/vec2/module.make @@ -0,0 +1 @@ +SRC += diff --git a/src/abc8/vec2/vec2.h b/src/abc8/vec2/vec2.h new file mode 100644 index 00000000..a4bd4771 --- /dev/null +++ b/src/abc8/vec2/vec2.h @@ -0,0 +1,121 @@ +/**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 + +#ifndef SINT64 +#define SINT64 + +#ifdef _WIN32 +typedef signed __int64 sint64; // compatible with MS VS 6.0 +#else +typedef long long sint64; +#endif + +#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/abc8/vec2/vecAtt.h b/src/abc8/vec2/vecAtt.h new file mode 100644 index 00000000..da7a8445 --- /dev/null +++ b/src/abc8/vec2/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/src/abc8/vec2/vecFlt.h b/src/abc8/vec2/vecFlt.h new file mode 100644 index 00000000..6b36ce84 --- /dev/null +++ b/src/abc8/vec2/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/src/abc8/vec2/vecInt.h b/src/abc8/vec2/vecInt.h new file mode 100644 index 00000000..082ebe70 --- /dev/null +++ b/src/abc8/vec2/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/src/abc8/vec2/vecPtr.h b/src/abc8/vec2/vecPtr.h new file mode 100644 index 00000000..9595bc72 --- /dev/null +++ b/src/abc8/vec2/vecPtr.h @@ -0,0 +1,812 @@ +/**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 [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 [] + + 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; +} + + + +/**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 [Cleans simulation info of each entry beginning with iWord.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrCleanSimInfo( Vec_Ptr_t * vInfo, int iWord, int nWords ) +{ + int i; + for ( i = 0; i < vInfo->nSize; i++ ) + memset( (char*)Vec_PtrEntry(vInfo,i) + 4*iWord, 0, 4*(nWords-iWord) ); +} + +/**Function************************************************************* + + Synopsis [Resizes the array of simulation info.] + + Description [Doubles the number of objects for which siminfo is allocated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo ) +{ + Vec_Ptr_t * vInfoNew; + int nWords; + assert( Vec_PtrSize(vInfo) > 1 ); + // 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 [Resizes the array of simulation info.] + + Description [Doubles the number of simulation patterns stored for each object.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrReallocSimInfo( Vec_Ptr_t * vInfo ) +{ + Vec_Ptr_t * vInfoNew; + int nWords, i; + assert( Vec_PtrSize(vInfo) > 1 ); + // get the new array + nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0); + vInfoNew = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), 2*nWords ); + // copy the simulation info + for ( i = 0; i < vInfo->nSize; i++ ) + memcpy( Vec_PtrEntry(vInfoNew,i), Vec_PtrEntry(vInfo,i), nWords * 4 ); + // replace the array + free( vInfo->pArray ); + vInfo->pArray = vInfoNew->pArray; + // free the old array + vInfoNew->pArray = NULL; + free( vInfoNew ); +} + +/**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; +} + +#endif + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/abc8/vec2/vecStr.h b/src/abc8/vec2/vecStr.h new file mode 100644 index 00000000..47367bc6 --- /dev/null +++ b/src/abc8/vec2/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/src/abc8/vec2/vecVec.h b/src/abc8/vec2/vecVec.h new file mode 100644 index 00000000..55ffdf4f --- /dev/null +++ b/src/abc8/vec2/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/src/aig/aig/aig.h b/src/aig/aig/aig.h deleted file mode 100644 index 5bff39f7..00000000 --- a/src/aig/aig/aig.h +++ /dev/null @@ -1,619 +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; - -// 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 - Aig_Obj_t * pHaig; // pointer to the HAIG node - 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 - void * pManTime; // the timing manager - void * pManCuts; - Vec_Ptr_t * vMapped; - Vec_Int_t * vFlopNums; - void * pSeqModel; - Aig_Man_t * pManHaig; - // timing statistics - int time1; - int time2; -}; - -// cut computation -typedef struct Aig_ManCut_t_ Aig_ManCut_t; -typedef struct Aig_Cut_t_ Aig_Cut_t; - -// the cut used to represent node in the AIG -struct Aig_Cut_t_ -{ - Aig_Cut_t * pNext; // the next cut in the table - int 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 Aig_ManCut_t_ -{ - // AIG manager - Aig_Man_t * pAig; // the input AIG manager - Aig_Cut_t ** pCuts; // the cuts for each node in the output manager - // parameters - int nCutsMax; // the max number of cuts at the node - int nLeafMax; // the max number of leaves of a cut - int fTruth; // enables truth table computation - 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 -}; - -static inline Aig_Cut_t * Aig_ObjCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } -static inline void Aig_ObjSetCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; } - -static inline int Aig_CutLeaveNum( Aig_Cut_t * pCut ) { return pCut->nFanins; } -static inline int * Aig_CutLeaves( Aig_Cut_t * pCut ) { return pCut->pFanins; } -static inline unsigned * Aig_CutTruth( Aig_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); } -static inline Aig_Cut_t * Aig_CutNext( Aig_Cut_t * pCut ) { return (Aig_Cut_t *)(((char *)pCut) + pCut->nCutSize); } - -// iterator over cuts of the node -#define Aig_ObjForEachCut( p, pObj, pCut, i ) \ - for ( i = 0, pCut = Aig_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Aig_CutNext(pCut) ) -// iterator over leaves of the cut -#define Aig_CutForEachLeaf( p, pCut, pLeaf, i ) \ - for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// 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_Float2Int( float Val ) { return *((int *)&Val); } -static inline float Aig_Int2Float( int Num ) { return *((float *)&Num); } -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 int Aig_WordFindFirstBit( unsigned uWord ) -{ - int i; - for ( i = 0; i < 32; i++ ) - if ( uWord & (1 << i) ) - return i; - return -1; -} - -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 void Aig_ObjChild0Flip( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); pObj->pFanin0 = Aig_Not(pObj->pFanin0); } -static inline void Aig_ObjChild1Flip( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); pObj->pFanin1 = Aig_Not(pObj->pFanin1); } -static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level; } -static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(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 int Aig_ObjSetLevel( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level = i; } -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 Aig_Obj_t * Aig_ObjHaig( Aig_Obj_t * pObj ) { assert( Aig_Regular(pObj)->pHaig ); return Aig_NotCond( Aig_Regular(pObj)->pHaig, Aig_IsComplement(pObj) ); } -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 ); -/*=== aigCuts.c ========================================================*/ -extern Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ); -extern void Aig_ManCutStop( Aig_ManCut_t * p ); -/*=== aigDfs.c ==========================================================*/ -extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ); -extern Vec_Ptr_t * Aig_ManDfsPio( 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 ); -/*=== aigFrames.c ==========================================================*/ -extern Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ); -/*=== aigHaig.c ==========================================================*/ -extern void Aig_ManHaigRecord( 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 Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize ); -extern Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize, int fVerbose ); -/*=== 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 ); -/*=== aigRetF.c ========================================================*/ -extern Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax ); -/*=== 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 ); -extern void Aig_TableClear( 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 ); - -#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/aigCuts.c b/src/aig/aig/aigCuts.c deleted file mode 100644 index 494d0d5b..00000000 --- a/src/aig/aig/aigCuts.c +++ /dev/null @@ -1,669 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigCuts.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Computation of K-feasible priority cuts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigCuts.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the cut sweeping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_ManCut_t * Aig_ManCutStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ) -{ - Aig_ManCut_t * p; - assert( nCutsMax >= 2 ); - assert( nLeafMax <= 16 ); - // allocate the fraiging manager - p = ALLOC( Aig_ManCut_t, 1 ); - memset( p, 0, sizeof(Aig_ManCut_t) ); - p->nCutsMax = nCutsMax; - p->nLeafMax = nLeafMax; - p->fTruth = fTruth; - p->fVerbose = fVerbose; - p->pAig = pMan; - // allocate room for cuts and equivalent nodes - p->pCuts = ALLOC( Aig_Cut_t *, Aig_ManObjNumMax(pMan) ); - memset( p->pCuts, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pMan) ); - // allocate memory manager - p->nTruthWords = Aig_TruthWordNum(nLeafMax); - p->nCutSize = sizeof(Aig_Cut_t) + sizeof(int) * nLeafMax + fTruth * sizeof(unsigned) * p->nTruthWords; - p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 ); - // room for temporary truth tables - if ( fTruth ) - { - 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 Aig_ManCutStop( Aig_ManCut_t * p ) -{ - Aig_MmFixedStop( p->pMemCuts, 0 ); - FREE( p->puTemp[0] ); - free( p->pCuts ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prints one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_CutPrint( Aig_Cut_t * pCut ) -{ - int i; - printf( "{" ); - for ( i = 0; i < pCut->nFanins; i++ ) - printf( " %d", pCut->pFanins[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCutPrint( Aig_ManCut_t * p, Aig_Obj_t * pObj ) -{ - Aig_Cut_t * pCut; - int i; - printf( "Cuts for node %d:\n", pObj->Id ); - Aig_ObjForEachCut( p, pObj, pCut, i ) - if ( pCut->nFanins ) - Aig_CutPrint( pCut ); -// printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Computes the total number of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCutCount( Aig_ManCut_t * p, int * pnCutsK ) -{ - Aig_Cut_t * pCut; - Aig_Obj_t * pObj; - int i, k, nCuts = 0, nCutsK = 0; - Aig_ManForEachNode( p->pAig, pObj, i ) - Aig_ObjForEachCut( p, pObj, pCut, k ) - { - if ( pCut->nFanins == 0 ) - continue; - nCuts++; - if ( pCut->nFanins == p->nLeafMax ) - nCutsK++; - } - if ( pnCutsK ) - *pnCutsK = nCutsK; - return nCuts; -} - -/**Function************************************************************* - - Synopsis [Compute the cost of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Aig_CutFindCost( Aig_ManCut_t * p, Aig_Cut_t * pCut ) -{ - Aig_Obj_t * pLeaf; - int i, Cost = 0; - assert( pCut->nFanins > 0 ); - Aig_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) - Cost += pLeaf->nRefs; - return Cost * 1000 / pCut->nFanins; -} - -/**Function************************************************************* - - Synopsis [Compute the cost of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Aig_CutFindCost2( Aig_ManCut_t * p, Aig_Cut_t * pCut ) -{ - Aig_Obj_t * pLeaf; - float Cost = 0.0; - int i; - assert( pCut->nFanins > 0 ); - Aig_CutForEachLeaf( p->pAig, 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 Aig_Cut_t * Aig_CutFindFree( Aig_ManCut_t * p, Aig_Obj_t * pObj ) -{ - Aig_Cut_t * pCut, * pCutMax; - int i; - pCutMax = NULL; - Aig_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 Aig_CutTruthPhase( Aig_Cut_t * pCut, Aig_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 * Aig_CutComputeTruth( Aig_ManCut_t * p, Aig_Cut_t * pCut, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, int fCompl0, int fCompl1 ) -{ - // permute the first table - if ( fCompl0 ) - Kit_TruthNot( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax ); - else - Kit_TruthCopy( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax ); - Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut0), 0 ); - // permute the second table - if ( fCompl1 ) - Kit_TruthNot( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax ); - else - Kit_TruthCopy( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax ); - Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut1), 0 ); - // produce the resulting table - Kit_TruthAnd( Aig_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax ); -// assert( pCut->nFanins >= Kit_TruthSupportSize( Aig_CutTruth(pCut), p->nLeafMax ) ); - return Aig_CutTruth(pCut); -} - -/**Function************************************************************* - - Synopsis [Performs support minimization for the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_CutSupportMinimize( Aig_ManCut_t * p, Aig_Cut_t * pCut ) -{ - unsigned * pTruth; - int uSupp, nFansNew, i, k; - // get truth table - pTruth = Aig_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 Aig_CutCheckDominance( Aig_Cut_t * pDom, Aig_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 Aig_CutFilter( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCut ) -{ - Aig_Cut_t * pTemp; - int i; - // go through the cuts of the node - Aig_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 ( Aig_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 ( Aig_CutCheckDominance( pTemp, pCut ) ) - { - // remove the given - pCut->nFanins = 0; - return 1; - } - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Aig_CutMergeOrdered( Aig_ManCut_t * p, Aig_Cut_t * pC0, Aig_Cut_t * pC1, Aig_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 Aig_CutMerge( Aig_ManCut_t * p, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, Aig_Cut_t * pCut ) -{ - assert( p->nLeafMax > 0 ); - // merge the nodes - if ( pCut0->nFanins < pCut1->nFanins ) - { - if ( !Aig_CutMergeOrdered( p, pCut1, pCut0, pCut ) ) - return 0; - } - else - { - if ( !Aig_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) - return 0; - } - pCut->uSign = pCut0->uSign | pCut1->uSign; - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Cut_t * Aig_ObjPrepareCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv ) -{ - Aig_Cut_t * pCutSet, * pCut; - int i; - // create the cutset of the node - pCutSet = (Aig_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); - Aig_ObjSetCuts( p, pObj, pCutSet ); - Aig_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 ); - if ( p->fTruth ) - memset( Aig_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords ); - } - return pCutSet; -} - -/**Function************************************************************* - - Synopsis [Derives cuts for one node and sweeps this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjComputeCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv ) -{ - Aig_Cut_t * pCut0, * pCut1, * pCut, * pCutSet; - Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); - Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); - int i, k; - // the node is not processed yet - assert( Aig_ObjIsNode(pObj) ); - assert( Aig_ObjCuts(p, pObj) == NULL ); - // set up the first cut - pCutSet = Aig_ObjPrepareCuts( p, pObj, fTriv ); - // compute pair-wise cut combinations while checking table - Aig_ObjForEachCut( p, pFanin0, pCut0, i ) - if ( pCut0->nFanins > 0 ) - Aig_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 = Aig_CutFindFree( p, pObj ); - // assemble the new cut - if ( !Aig_CutMerge( p, pCut0, pCut1, pCut ) ) - { - assert( pCut->nFanins == 0 ); - continue; - } - // check containment - if ( Aig_CutFilter( p, pObj, pCut ) ) - { - assert( pCut->nFanins == 0 ); - continue; - } - // create its truth table - if ( p->fTruth ) - Aig_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); - // assign the cost - pCut->Cost = Aig_CutFindCost( p, pCut ); - assert( pCut->nFanins > 0 ); - assert( pCut->Cost > 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for all nodes in the static AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ) -{ - Aig_ManCut_t * p; - Aig_Obj_t * pObj; - int i, clk = clock(); - assert( pAig->pManCuts == NULL ); - // start the manager - p = Aig_ManCutStart( pAig, nCutsMax, nLeafMax, fTruth, fVerbose ); - // set elementary cuts at the PIs - Aig_ManForEachPi( pAig, pObj, i ) - Aig_ObjPrepareCuts( p, pObj, 1 ); - // process the nodes - Aig_ManForEachNode( pAig, pObj, i ) - Aig_ObjComputeCuts( p, pObj, 1 ); - // print stats - if ( fVerbose ) - { - int nCuts, nCutsK; - nCuts = Aig_ManCutCount( p, &nCutsK ); - printf( "Nodes = %6d. Total cuts = %6d. %d-input cuts = %6d.\n", - Aig_ManObjNum(pAig), nCuts, nLeafMax, nCutsK ); - printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f Mb ", - p->nCutSize, 4*p->nTruthWords, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); - PRT( "Runtime", clock() - clk ); -/* - Aig_ManForEachNode( pAig, pObj, i ) - if ( i % 300 == 0 ) - Aig_ObjCutPrint( p, pObj ); -*/ - } - // remember the cut manager - pAig->pManCuts = p; - return p; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigDfs.c b/src/aig/aig/aigDfs.c deleted file mode 100644 index c7488487..00000000 --- a/src/aig/aig/aigDfs.c +++ /dev/null @@ -1,723 +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_ManDfsPio( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - Aig_ManIncrementTravId( p ); - vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); - Aig_ManForEachPo( p, pObj, i ) - 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/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/aigFrames.c b/src/aig/aig/aigFrames.c deleted file mode 100644 index 4a3b0c7c..00000000 --- a/src/aig/aig/aigFrames.c +++ /dev/null @@ -1,133 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigFrames.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Performs timeframe expansion of the AIG.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigFrames.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline Aig_Obj_t * Aig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; } -static inline void Aig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; } - -static inline Aig_Obj_t * Aig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs timeframe expansion of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; - Aig_Obj_t ** pObjMap; - int i, f; - - // create mapping for the frames nodes - pObjMap = ALLOC( Aig_Obj_t *, nFs * Aig_ManObjNumMax(pAig) ); - memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFs * Aig_ManObjNumMax(pAig) ); - - // start the fraig package - pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFs ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - // map constant nodes - for ( f = 0; f < nFs; f++ ) - Aig_ObjSetFrames( pObjMap, nFs, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); - // create PI nodes for the frames - for ( f = 0; f < nFs; f++ ) - Aig_ManForEachPiSeq( pAig, pObj, i ) - Aig_ObjSetFrames( pObjMap, nFs, pObj, f, Aig_ObjCreatePi(pFrames) ); - // set initial state for the latches - if ( fInit ) - { - Aig_ManForEachLoSeq( pAig, pObj, i ) - Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ManConst0(pFrames) ); - } - else - { - Aig_ManForEachLoSeq( pAig, pObj, i ) - Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ObjCreatePi(pFrames) ); - } - - // add timeframes - for ( f = 0; f < nFs; f++ ) - { -// printf( "Frame = %d.\n", f ); - // add internal nodes of this frame - Aig_ManForEachNode( pAig, pObj, i ) - { -// Aig_Obj_t * pFanin0 = Aig_ObjChild0Frames(pObjMap,nFs,pObj,f); -// Aig_Obj_t * pFanin1 = Aig_ObjChild1Frames(pObjMap,nFs,pObj,f); -// printf( "Node = %3d. Fanin0 = %3d. Fanin1 = %3d.\n", pObj->Id, Aig_Regular(pFanin0)->Id, Aig_Regular(pFanin1)->Id ); - pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f), Aig_ObjChild1Frames(pObjMap,nFs,pObj,f) ); - Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew ); - } - // set the latch inputs and copy them into the latch outputs of the next frame - Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) - { - pObjNew = Aig_ObjChild0Frames(pObjMap,nFs,pObjLi,f); - if ( f < nFs - 1 ) - Aig_ObjSetFrames( pObjMap, nFs, pObjLo, f+1, pObjNew ); - } - } - if ( fOuts ) - { - for ( f = fEnlarge?nFs-1:0; f < nFs; f++ ) - Aig_ManForEachPoSeq( pAig, pObj, i ) - { - pObjNew = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f) ); - Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew ); - } - } - if ( fRegs ) - { - pFrames->nRegs = pAig->nRegs; - Aig_ManForEachLiSeq( pAig, pObj, i ) - { - pObjNew = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,fEnlarge?0:nFs-1) ); - Aig_ObjSetFrames( pObjMap, nFs, pObj, nFs-1, pObjNew ); - } - } - Aig_ManCleanup( pFrames ); - // return the new manager - if ( ppObjMap ) - *ppObjMap = pObjMap; - else - free( pObjMap ); - return pFrames; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigHaig.c b/src/aig/aig/aigHaig.c deleted file mode 100644 index eaf9fd05..00000000 --- a/src/aig/aig/aigHaig.c +++ /dev/null @@ -1,270 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigHaig.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: aigHaig.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" -#include "satSolver.h" -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline Aig_Obj_t * Aig_HaigObjFrames( Aig_Obj_t ** ppMap, int nFrames, Aig_Obj_t * pObj, int f ) { return ppMap[nFrames*pObj->Id + f]; } -static inline void Aig_HaigObjSetFrames( Aig_Obj_t ** ppMap, int nFrames, Aig_Obj_t * pObj, int f, Aig_Obj_t * pNode ) { ppMap[nFrames*pObj->Id + f] = pNode; } -static inline Aig_Obj_t * Aig_HaigObjChild0Frames( Aig_Obj_t ** ppMap, int nFrames, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_HaigObjFrames(ppMap,nFrames,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Aig_HaigObjChild1Frames( Aig_Obj_t ** ppMap, int nFrames, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_HaigObjFrames(ppMap,nFrames,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs speculative reduction for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Aig_ManHaigFramesNode( Aig_Obj_t ** ppMap, int nFrames, Aig_Man_t * pFrames, Aig_Obj_t * pObj, int iFrame ) -{ - Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter; - // skip nodes without representative - pObjRepr = pObj->pHaig; - if ( pObjRepr == NULL ) - return; - assert( !Aig_IsComplement(pObjRepr) ); - assert( pObjRepr->Id < pObj->Id ); - // get the new node - pObjNew = Aig_HaigObjFrames( ppMap, nFrames, pObj, iFrame ); - // get the new node of the representative - pObjReprNew = Aig_HaigObjFrames( ppMap, nFrames, 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 - Aig_HaigObjSetFrames( ppMap, nFrames, pObj, iFrame, pObjNew2 ); - // add the constraint - pMiter = Aig_Exor( pFrames, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) ); - pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); - pMiter = Aig_Not( pMiter ); - Aig_ObjCreatePo( pFrames, pMiter ); -} - -/**Function************************************************************* - - Synopsis [Prepares the inductive case with speculative reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManHaigFrames( Aig_Man_t * pHaig, int nFrames ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; - Aig_Obj_t ** ppMap; - int i, k, f; - assert( nFrames >= 2 ); - assert( Aig_ManRegNum(pHaig) > 0 ); - assert( Aig_ManRegNum(pHaig) < Aig_ManPiNum(pHaig) ); - - // create node mapping - ppMap = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pHaig) * nFrames ); - memset( ppMap, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pHaig) * nFrames ); - - // start the frames - pFrames = Aig_ManStart( Aig_ManObjNumMax(pHaig) * nFrames ); - pFrames->pName = Aig_UtilStrsav( pHaig->pName ); - pFrames->nRegs = pHaig->nRegs; - - // create PI nodes for the frames - for ( f = 0; f < nFrames; f++ ) - Aig_HaigObjSetFrames( ppMap, nFrames, Aig_ManConst1(pHaig), f, Aig_ManConst1(pFrames) ); - for ( f = 0; f < nFrames; f++ ) - Aig_ManForEachPiSeq( pHaig, pObj, i ) - Aig_HaigObjSetFrames( ppMap, nFrames, pObj, f, Aig_ObjCreatePi(pFrames) ); - // create latches for the first frame - Aig_ManForEachLoSeq( pHaig, pObj, i ) - Aig_HaigObjSetFrames( ppMap, nFrames, pObj, 0, Aig_ObjCreatePi(pFrames) ); - - // add timeframes - for ( f = 0; f < nFrames; f++ ) - { - // mark the asserts - if ( f == nFrames - 1 ) - pFrames->nAsserts = Aig_ManPoNum(pFrames); - // constrain latch outputs and internal nodes - Aig_ManForEachObj( pHaig, pObj, i ) - { - if ( Aig_ObjIsPi(pObj) && Aig_HaigObjFrames(ppMap, nFrames, pObj, f) == NULL ) - { - Aig_ManHaigFramesNode( ppMap, nFrames, pFrames, pObj, f ); - } - else if ( Aig_ObjIsNode(pObj) ) - { - pObjNew = Aig_And( pFrames, - Aig_HaigObjChild0Frames(ppMap,nFrames,pObj,f), - Aig_HaigObjChild1Frames(ppMap,nFrames,pObj,f) ); - Aig_HaigObjSetFrames( ppMap, nFrames, pObj, f, pObjNew ); - Aig_ManHaigFramesNode( ppMap, nFrames, pFrames, pObj, f ); - } - } - -/* - // set the constraints on the latch outputs - Aig_ManForEachLoSeq( pHaig, pObj, i ) - Aig_ManHaigFramesNode( ppMap, nFrames, pFrames, pObj, f ); - // add internal nodes of this frame - Aig_ManForEachNode( pHaig, pObj, i ) - { - pObjNew = Aig_And( pFrames, - Aig_HaigObjChild0Frames(ppMap,nFrames,pObj,f), - Aig_HaigObjChild1Frames(ppMap,nFrames,pObj,f) ); - Aig_HaigObjSetFrames( ppMap, nFrames, pObj, f, pObjNew ); - Aig_ManHaigFramesNode( ppMap, nFrames, pFrames, pObj, f ); - } -*/ - // transfer latch inputs to the latch outputs - Aig_ManForEachLiLoSeq( pHaig, pObjLi, pObjLo, k ) - { - pObjNew = Aig_HaigObjChild0Frames(ppMap,nFrames,pObjLi,f); - Aig_HaigObjSetFrames( ppMap, nFrames, pObjLo, f+1, pObjNew ); - } - } - - // remove dangling nodes - Aig_ManCleanup( pFrames ); - free( ppMap ); - return pFrames; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManHaigVerify( Aig_Man_t * pHaig ) -{ - int nBTLimit = 0; - Aig_Man_t * pFrames; - Cnf_Dat_t * pCnf; - sat_solver * pSat; - Aig_Obj_t * pObj; - int i, Lit, RetValue, Counter; - int clk = clock(); - - // create time frames with speculative reduction and convert them into CNF -clk = clock(); - pFrames = Aig_ManHaigFrames( pHaig, 2 ); - pCnf = Cnf_DeriveSimple( pFrames, Aig_ManPoNum(pFrames) - pFrames->nAsserts ); -// pCnf = Cnf_Derive( pFrames, Aig_ManPoNum(pFrames) - pFrames->nAsserts ); -//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 ); - // create the SAT solver to be used for this problem - pSat = Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - - printf( "HAIG regs = %d. HAIG nodes = %d. Outputs = %d.\n", - Aig_ManRegNum(pHaig), Aig_ManNodeNum(pHaig), Aig_ManPoNum(pHaig) ); - printf( "Frames regs = %d. Frames nodes = %d. Outputs = %d. Assumptions = %d. Asserts = %d.\n", - Aig_ManRegNum(pFrames), Aig_ManNodeNum(pFrames), Aig_ManPoNum(pFrames), - pFrames->nAsserts, Aig_ManPoNum(pFrames) - pFrames->nAsserts ); - -PRT( "Preparation", clock() - clk ); - if ( pSat == NULL ) - { - printf( "Aig_ManHaigVerify(): Computed CNF is not valid.\n" ); - return -1; - } - - // solve each output -clk = clock(); - Counter = 0; - Aig_ManForEachPo( pFrames, pObj, i ) - { - if ( i < pFrames->nAsserts ) - continue; - Lit = toLitCond( pCnf->pVarNums[pObj->Id], pObj->fPhase ); - RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - if ( RetValue != l_False ) - Counter++; - } -PRT( "Solving ", clock() - clk ); - if ( Counter ) - printf( "Verification failed for %d classes.\n", Counter ); - else - printf( "Verification is successful.\n" ); - - // clean up - Aig_ManStop( pFrames ); - Cnf_DataFree( pCnf ); - sat_solver_delete( pSat ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManHaigRecord( Aig_Man_t * p ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i; - // start the HAIG - p->pManHaig = Aig_ManDup( p, 1 ); - // set the pointers to the HAIG nodes - Aig_ManForEachObj( p, pObj, i ) - pObj->pHaig = pObj->pData; - // remove structural hashing table - Aig_TableClear( p->pManHaig ); - // perform a sequence of synthesis steps - pNew = Aig_ManRetimeFrontier( p, 10000 ); - // use the haig for verification - Aig_ManDumpBlif( pNew->pManHaig, "haig_temp.blif" ); - Aig_ManHaigVerify( pNew->pManHaig ); - Aig_ManStop( pNew ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigInter.c b/src/aig/aig/aigInter.c deleted file mode 100644 index b3bc28b2..00000000 --- a/src/aig/aig/aigInter.c +++ /dev/null @@ -1,174 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigInter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Interpolate two AIGs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigInter.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" -#include "cnf.h" -#include "satStore.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose ) -{ - void * pSatCnf = NULL; - Inta_Man_t * pManInter; - Aig_Man_t * pRes; - sat_solver * pSat; - Cnf_Dat_t * pCnfOn, * pCnfOff; - Vec_Int_t * vVarsAB; - Aig_Obj_t * pObj, * pObj2; - int Lits[3], status, i; - int clk = clock(); - - assert( Aig_ManPiNum(pManOn) == Aig_ManPiNum(pManOff) ); - - // derive CNFs - pCnfOn = Cnf_Derive( pManOn, 0 ); - pCnfOff = Cnf_Derive( pManOff, 0 ); -// pCnfOn = Cnf_DeriveSimple( pManOn, 0 ); -// pCnfOff = Cnf_DeriveSimple( pManOff, 0 ); - Cnf_DataLift( pCnfOff, pCnfOn->nVars ); - - // start the solver - pSat = sat_solver_new(); - sat_solver_store_alloc( pSat ); - sat_solver_setnvars( pSat, pCnfOn->nVars + pCnfOff->nVars ); - - // add clauses of A - for ( i = 0; i < pCnfOn->nClauses; i++ ) - { - if ( !sat_solver_addclause( pSat, pCnfOn->pClauses[i], pCnfOn->pClauses[i+1] ) ) - { - Cnf_DataFree( pCnfOn ); - Cnf_DataFree( pCnfOff ); - sat_solver_delete( pSat ); - return NULL; - } - } - sat_solver_store_mark_clauses_a( pSat ); - - // add clauses of B - for ( i = 0; i < pCnfOff->nClauses; i++ ) - { - if ( !sat_solver_addclause( pSat, pCnfOff->pClauses[i], pCnfOff->pClauses[i+1] ) ) - { - Cnf_DataFree( pCnfOn ); - Cnf_DataFree( pCnfOff ); - sat_solver_delete( pSat ); - return NULL; - } - } - - // add PI clauses - // collect the common variables - vVarsAB = Vec_IntAlloc( Aig_ManPiNum(pManOn) ); - Aig_ManForEachPi( pManOn, pObj, i ) - { - Vec_IntPush( vVarsAB, pCnfOn->pVarNums[pObj->Id] ); - pObj2 = Aig_ManPi( pManOff, i ); - - Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 ); - Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 1 ); - Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - } - Cnf_DataFree( pCnfOn ); - Cnf_DataFree( pCnfOff ); - sat_solver_store_mark_roots( pSat ); - if ( fVerbose ) - { - PRT( "Prepare", clock() - clk ); - } - -/* - status = sat_solver_simplify(pSat); - if ( status == 0 ) - { - Vec_IntFree( vVarsAB ); - Cnf_DataFree( pCnfOn ); - Cnf_DataFree( pCnfOff ); - sat_solver_delete( pSat ); - return NULL; - } -*/ - - // solve the problem - clk = clock(); - status = sat_solver_solve( pSat, NULL, NULL, (sint64)0, (sint64)0, (sint64)0, (sint64)0 ); - if ( fVerbose ) - { - PRT( "Solving", clock() - clk ); - } - if ( status == l_False ) - { - pSatCnf = sat_solver_store_release( pSat ); -// printf( "unsat\n" ); - } - else if ( status == l_True ) - { -// printf( "sat\n" ); - } - else - { -// printf( "undef\n" ); - } - sat_solver_delete( pSat ); - if ( pSatCnf == NULL ) - { - printf( "The SAT problem is not unsat.\n" ); - Vec_IntFree( vVarsAB ); - return NULL; - } - - // create the resulting manager - pManInter = Inta_ManAlloc(); - pRes = Inta_ManInterpolate( pManInter, pSatCnf, vVarsAB, fVerbose ); - Inta_ManFree( pManInter ); - - Vec_IntFree( vVarsAB ); - Sto_ManFree( pSatCnf ); - return pRes; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigMan.c b/src/aig/aig/aigMan.c deleted file mode 100644 index 1388c73e..00000000 --- a/src/aig/aig/aigMan.c +++ /dev/null @@ -1,369 +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" -#include "tim.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) ); - if ( pNew->pManHaig == NULL ) - return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - else - { - Aig_Obj_t * pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - Aig_Regular(pObjNew->pHaig)->pHaig = Aig_Regular(pObj->pHaig); - return pObj->pData = pObjNew; - } -} - -/**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, * pObjNew; - 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; - pNew->pManHaig = p->pManHaig; - if ( p->vFlopNums ) - pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); - // create the PIs - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManConst1(pNew)->pHaig = Aig_ManConst1(p)->pHaig; - Aig_ManForEachPi( p, pObj, i ) - { - pObjNew = Aig_ObjCreatePi( pNew ); - pObjNew->pHaig = pObj->pHaig; - pObjNew->Level = pObj->Level; - pObj->pData = pObjNew; - } - // duplicate internal nodes - if ( fOrdered ) - { - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjIsBuf(pObj) ) - { - if ( pNew->pManHaig == NULL ) - pObj->pData = Aig_ObjChild0Copy(pObj); - else - { - Aig_Obj_t * pObjNew = Aig_ObjChild0Copy(pObj); - Aig_Regular(pObjNew->pHaig)->pHaig = Aig_Regular(pObj->pHaig); - pObj->pData = pObjNew; - } - } - else if ( Aig_ObjIsNode(pObj) ) - { - if ( pNew->pManHaig == NULL ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - else - { - Aig_Obj_t * pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - Aig_Regular(pObjNew->pHaig)->pHaig = Aig_Regular(pObj->pHaig); - pObj->pData = pObjNew; - } - } - } - 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 ) - { - pObjNew = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - pObjNew->pHaig = pObj->pHaig; - pObj->pData = pObjNew; - } - assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); - // pass the HAIG to the new AIG - p->pManHaig = NULL; - Aig_ManForEachObj( p, pObj, i ) - pObj->pHaig = NULL; - // 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->pManHaig ) - Aig_ManStop( p->pManHaig ); - 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 ) - Tim_ManStop( 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->pSeqModel ); - 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/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 80838e19..00000000 --- a/src/aig/aig/aigObj.c +++ /dev/null @@ -1,431 +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 ); - if ( p->pManHaig ) - { - pGhost->pFanin0 = Aig_ObjHaig( pGhost->pFanin0 ); - pGhost->pFanin1 = Aig_ObjHaig( pGhost->pFanin1 ); - pObj->pHaig = Aig_ObjCreate( p->pManHaig, pGhost ); - } - 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) ); - // map the HAIG nodes - if ( p->pManHaig != NULL ) - { - assert( pObjNewR->pHaig != NULL ); - assert( pObjNewR->pHaig->pHaig == NULL ); - pObjNewR->pHaig->pHaig = pObjOld->pHaig; - } - // 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 ); - // update the haig node - pObjOld->pHaig = pObjNew->pHaig; - // 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 c19f551e..00000000 --- a/src/aig/aig/aigOper.c +++ /dev/null @@ -1,541 +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; - if ( p->pTable == NULL ) - { -// pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND ); - pGhost = Aig_ManGhost(p); - pGhost->Type = AIG_OBJ_AND; - pGhost->pFanin0 = p0; - pGhost->pFanin1 = p1; - return Aig_ObjCreate( p, pGhost ); - } - // 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 de13653c..00000000 --- a/src/aig/aig/aigPart.c +++ /dev/null @@ -1,992 +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 *)(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 partition and its 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, int fVerbose ) -{ -// 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 - if ( fVerbose ) - 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 ); - } - if ( fVerbose ) - 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 5ee6c9af..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 d1784b1b..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/aigRetF.c b/src/aig/aig/aigRetF.c deleted file mode 100644 index 8ca4fba1..00000000 --- a/src/aig/aig/aigRetF.c +++ /dev/null @@ -1,219 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigRetF.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Retiming frontier.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigRetF.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Mark the nodes reachable from the PIs in the reverse order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManRetimeMark_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( pObj->fMarkB ) - return 1; - if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) - return 0; - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return pObj->fMarkB; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Aig_ManRetimeMark_rec( p, Aig_ObjFanin0(pObj) ) ) - return pObj->fMarkB = 1; - if ( Aig_ObjIsNode(pObj) && Aig_ManRetimeMark_rec( p, Aig_ObjFanin1(pObj) ) ) - return pObj->fMarkB = 1; - assert( pObj->fMarkB == 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Mark the nodes reachable from the true PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManRetimeMark( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int fChange, i; - // mark the PIs - Aig_ManForEachObj( p, pObj, i ) - assert( pObj->fMarkB == 0 ); - Aig_ManForEachPiSeq( p, pObj, i ) - pObj->fMarkB = 1; - // map registers into each other - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - { - assert( pObjLo->pNext == NULL ); - assert( pObjLi->pNext == NULL ); - pObjLo->pNext = pObjLi; - pObjLi->pNext = pObjLo; - } - // iterativively mark the logic reachable from PIs - fChange = 1; - while ( fChange ) - { - fChange = 0; - Aig_ManIncrementTravId( p ); - Aig_ManForEachPo( p, pObj, i ) - { - if ( pObj->fMarkB ) - continue; - if ( Aig_ManRetimeMark_rec( p, pObj ) ) - { - if ( pObj->pNext ) - pObj->pNext->fMarkB = 1; - fChange = 1; - } - } - } - // clean register mapping - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - pObjLo->pNext = pObjLi->pNext = NULL; -} - - -/**Function************************************************************* - - Synopsis [Performs forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax ) -{ - Aig_Obj_t * pObj, * pObjNew, * pObjLo, * pObjLo0, * pObjLo1, * pObjLi, * pObjLi0, * pObjLi1;//, * pObjLi0_, * pObjLi1_, * pObjLi0__, * pObjLi1__; - int i, Counter, fCompl, fChange; - assert( Aig_ManRegNum(p) > 0 ); - // remove structural hashing table - Aig_TableClear( p ); - // mark the retimable nodes - Aig_ManRetimeMark( p ); - // mark the register outputs - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - { - pObjLo->fMarkA = 1; - pObjLo->pNext = pObjLi; - pObjLi->pNext = pObjLo; - } - // go through the nodes and find retimable ones - Counter = 0; - fChange = 1; - while ( fChange ) - { - fChange = 0; - Aig_ManForEachNode( p, pObj, i ) - { - if ( !pObj->fMarkB ) - continue; - if ( Aig_ObjIsBuf(pObj) ) - continue; - // get the real inputs of the node (skipping the buffers) - pObjLo0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - pObjLo1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); - if ( !Aig_Regular(pObjLo0)->fMarkA || !Aig_Regular(pObjLo1)->fMarkA ) - continue; - // remember complemented attribute - fCompl = Aig_IsComplement(pObjLo0) & Aig_IsComplement(pObjLo1); - // get the register inputs -// pObjLi0_ = Aig_Regular(pObjLo0)->pNext; -// pObjLi1_ = Aig_Regular(pObjLo1)->pNext; -// pObjLi0__ = Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext); -// pObjLi1__ = Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext); - pObjLi0 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext), Aig_IsComplement(pObjLo0) ); - pObjLi1 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext), Aig_IsComplement(pObjLo1) ); - // create new node - pObjNew = Aig_And( p, pObjLi0, pObjLi1 ); - pObjNew->fMarkB = 1; - // create new register - pObjLo = Aig_ObjCreatePi(p); - pObjLo->fMarkA = 1; - pObjLi = Aig_ObjCreatePo( p, Aig_NotCond(pObjNew, fCompl) ); - p->nRegs++; - pObjLo->pNext = pObjLi; - pObjLi->pNext = pObjLo; - // add the buffer - Aig_ObjDisconnect( p, pObj ); - pObj->Type = AIG_OBJ_BUF; - p->nObjs[AIG_OBJ_AND]--; - p->nObjs[AIG_OBJ_BUF]++; - Aig_ObjConnect( p, pObj, Aig_NotCond(pObjLo, fCompl), NULL ); - // create HAIG if defined - if ( p->pManHaig ) - { - // create HAIG latch - pObjLo->pHaig = Aig_ObjCreatePi( p->pManHaig ); - pObjLi->pHaig = Aig_ObjCreatePo( p->pManHaig, Aig_ObjHaig( Aig_ObjChild0(pObjLi) ) ); - // create equivalence class - assert( pObjLo->pHaig != NULL ); - assert( pObjLo->pHaig->pHaig == NULL ); - pObjLo->pHaig->pHaig = Aig_Regular(pObj->pHaig); - } - // mark the change - fChange = 1; - // check the limit - if ( ++Counter >= nStepsMax ) - { - fChange = 0; - break; - } - } - } - // clean the markings - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - { - pObjLo->fMarkA = 0; - pObjLo->pNext = pObjLi->pNext = NULL; - } - Aig_ManForEachObj( p, pObj, i ) - pObj->fMarkB = 0; - // remove useless registers - Aig_ManSeqCleanup( p ); - // rehash the nodes - return Aig_ManDup( p, 1 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigScl.c b/src/aig/aig/aigScl.c deleted file mode 100644 index 9721dd17..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 node 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_ObjIsBuf(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/src/aig/aig/aigSeq.c b/src/aig/aig/aigSeq.c deleted file mode 100644 index daafeab1..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 357b63c3..00000000 --- a/src/aig/aig/aigTable.c +++ /dev/null @@ -1,289 +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; - if ( p->pTable == NULL ) - return; - 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; - if ( p->pTable == NULL ) - return; - 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 ); - } -} - -/**Function******************************************************************** - - Synopsis [Profiles the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Aig_TableClear( Aig_Man_t * p ) -{ - FREE( p->pTable ); - p->nTableSize = 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigTiming.c b/src/aig/aig/aigTiming.c deleted file mode 100644 index de8fdc7c..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 = -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/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 a8a3dda8..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 f6f34de9..00000000 --- a/src/aig/aig/aigUtil.c +++ /dev/null @@ -1,855 +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? "!" : "", (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 a 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; - } - // check if constant is used - Aig_ManForEachPo( p, pObj, i ) - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) - pConst1 = Aig_ManConst1(p); - // 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 - if ( pConst1 ) - fprintf( pFile, ".names n%0*d\n 1\n", nDigits, pConst1->iData ); - 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) ); - } - fprintf( pFile, ".end\n\n" ); - fclose( pFile ); - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Writes the AIG into a Verilog 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; - } - // check if constant is used - Aig_ManForEachPo( p, pObj, i ) - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) - pConst1 = Aig_ManConst1(p); - // 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 ); - if ( pConst1 ) - fprintf( pFile, "wire n%0*d;\n", nDigits, pConst1->iData ); - // write nodes - if ( pConst1 ) - fprintf( pFile, "assign n%0*d = 1\'b1;\n", nDigits, pConst1->iData ); - 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_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 ); - } - } - - // 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 ffe6141c..00000000 --- a/src/aig/aig/module.make +++ /dev/null @@ -1,25 +0,0 @@ -SRC += src/aig/aig/aigCheck.c \ - src/aig/aig/aigDfs.c \ - src/aig/aig/aigFanout.c \ - src/aig/aig/aigFrames.c \ - src/aig/aig/aigHaig.c \ - src/aig/aig/aigInter.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/aigRetF.c \ - src/aig/aig/aigScl.c \ - src/aig/aig/aigSeq.c \ - src/aig/aig/aigShow.c \ - src/aig/aig/aigTable.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 5726469f..00000000 --- a/src/aig/cnf/cnf.h +++ /dev/null @@ -1,163 +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_DataLift( Cnf_Dat_t * p, int nVarsPlus ); -extern void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable ); -void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ); -/*=== 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 e1d62de0..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, 0 ); -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 01f6ff8a..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[(int)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[(int)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 47bc0b67..00000000 --- a/src/aig/cnf/cnfMan.c +++ /dev/null @@ -1,282 +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_DataLift( Cnf_Dat_t * p, int nVarsPlus ) -{ - Aig_Obj_t * pObj; - int v; - Aig_ManForEachObj( p->pMan, pObj, v ) - if ( p->pVarNums[pObj->Id] ) - p->pVarNums[pObj->Id] += nVarsPlus; - for ( v = 0; v < p->nLiterals; v++ ) - p->pClauses[0][v] += 2*nVarsPlus; -} - -/**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, int nFrames, int fInit ) -{ - sat_solver * pSat; - int i, f, status; - assert( nFrames > 0 ); - pSat = sat_solver_new(); - sat_solver_setnvars( pSat, p->nVars * nFrames ); - 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; - } - } - if ( nFrames > 1 ) - { - Aig_Obj_t * pObjLo, * pObjLi; - int nLitsAll, * pLits, Lits[2]; - nLitsAll = 2 * p->nVars; - pLits = p->pClauses[0]; - for ( f = 1; f < nFrames; f++ ) - { - // add equality of register inputs/outputs for different timeframes - Aig_ManForEachLiLoSeq( p->pMan, pObjLi, pObjLo, i ) - { - Lits[0] = (f-1)*nLitsAll + toLitCond( p->pVarNums[pObjLi->Id], 0 ); - Lits[1] = f *nLitsAll + toLitCond( p->pVarNums[pObjLo->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - Lits[0]++; - Lits[1]--; - if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - } - // add clauses for the next timeframe - for ( i = 0; i < p->nLiterals; i++ ) - pLits[i] += nLitsAll; - 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; - } - } - } - // return literals to their original state - nLitsAll = (f-1) * nLitsAll; - for ( i = 0; i < p->nLiterals; i++ ) - pLits[i] -= nLitsAll; - } - if ( fInit ) - { - Aig_Obj_t * pObjLo; - int Lits[1]; - Aig_ManForEachLoSeq( p->pMan, pObjLo, i ) - { - Lits[0] = toLitCond( p->pVarNums[pObjLo->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 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 8c23d859..00000000 --- a/src/aig/cnf/cnfWrite.c +++ /dev/null @@ -1,445 +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->pMan = p->pManAig; - 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. - New variables will be introduced for these outputs.] - - 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->pMan = p; - 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 72e7d3d1..00000000 --- a/src/aig/dar/dar.h +++ /dev/null @@ -1,106 +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 /// -//////////////////////////////////////////////////////////////////////// - -/*=== 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, int fVerbose ); -/*=== 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 b3c5d645..00000000 --- a/src/aig/dar/darBalance.c +++ /dev/null @@ -1,400 +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 141d9b79..00000000 --- a/src/aig/dar/darCore.c +++ /dev/null @@ -1,289 +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 [Computes the total number of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_ManCutCount( Aig_Man_t * pAig, int * pnCutsK ) -{ - Dar_Cut_t * pCut; - Aig_Obj_t * pObj; - int i, k, nCuts = 0, nCutsK = 0; - Aig_ManForEachNode( pAig, pObj, i ) - Dar_ObjForEachCut( pObj, pCut, k ) - { - nCuts++; - if ( pCut->nLeaves == 4 ) - nCutsK++; - } - if ( pnCutsK ) - *pnCutsK = nCutsK; - return nCuts; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax, int fVerbose ) -{ - Dar_Man_t * p; - Dar_RwrPar_t Pars, * pPars = &Pars; - Aig_Obj_t * pObj; - Aig_MmFixed_t * pMemCuts; - int i, nNodes, clk = 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 ); - // print verbose stats - if ( fVerbose ) - { -// Aig_Obj_t * pObj; - int nCuts, nCutsK;//, i; - nCuts = Dar_ManCutCount( pAig, &nCutsK ); - printf( "Nodes = %6d. Total cuts = %6d. 4-input cuts = %6d.\n", - Aig_ManObjNum(pAig), nCuts, nCutsK ); - printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f Mb ", - sizeof(Dar_Cut_t), 4, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); - PRT( "Runtime", clock() - clk ); -/* - Aig_ManForEachNode( pAig, pObj, i ) - if ( i % 300 == 0 ) - Dar_ObjCutPrint( pAig, 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 79e4dcc4..00000000 --- a/src/aig/dar/darCut.c +++ /dev/null @@ -1,739 +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 [Prints one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_CutPrint( Dar_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 Dar_ObjCutPrint( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Dar_Cut_t * pCut; - int i; - printf( "Cuts for node %d:\n", pObj->Id ); - Dar_ObjForEachCut( pObj, pCut, i ) - Dar_CutPrint( pCut ); -// printf( "\n" ); -} - -/**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 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 cb403b8a..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 afa3bd07..00000000 --- a/src/aig/dar/darInt.h +++ /dev/null @@ -1,166 +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 "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 ); -extern void Dar_ObjCutPrint( Aig_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 e0e97055..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[ (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/src/aig/dar/darMan.c b/src/aig/dar/darMan.c deleted file mode 100644 index 0a5a36b1..00000000 --- a/src/aig/dar/darMan.c +++ /dev/null @@ -1,133 +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 ); - printf( "\n" ); - } -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darPrec.c b/src/aig/dar/darPrec.c deleted file mode 100644 index 8c3a4ce3..00000000 --- a/src/aig/dar/darPrec.c +++ /dev/null @@ -1,387 +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 [] - -***********************************************************************/ -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/src/aig/dar/darRefact.c b/src/aig/dar/darRefact.c deleted file mode 100644 index a765ec30..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 = 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/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 530e913e..00000000 --- a/src/aig/dar/darScript.c +++ /dev/null @@ -1,393 +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( pAig, 0 ); - 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( pAig, 0 ); - 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, 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 ); - - 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, fVerbose ); - 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/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 b1b0332c..00000000 --- a/src/aig/dar/module.make +++ /dev/null @@ -1,10 +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 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 8d7116c7..00000000 --- a/src/aig/fra/fra.h +++ /dev/null @@ -1,324 +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_Cex_t_ Fra_Cex_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 nMaxLevs; // the maximum number of levels to consider - int fRewrite; // use rewriting for constraint reduction - int fLatchCorr; // computes latch correspondence only - int fUseImps; // use implications - int fWriteImps; // record implications - int fDontShowBar; // does not show progressbar during fraiging -}; - -// 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 -}; - -// simulation manager -struct Fra_Cex_t_ -{ - int iPo; // the zero-based number of PO, for which verification failed - int iFrame; // the zero-based number of the time-frame, for which verificaiton failed - int nRegs; // the number of registers in the miter - int nPis; // the number of primary inputs in the miter - int nBits; // the number of words of bit data used - unsigned pData[0]; // the cex bit data (the number of bits: nRegs + (iFrame+1) * nPis) -}; - -// 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 /// -//////////////////////////////////////////////////////////////////////// - -/*=== fraCec.c ========================================================*/ -extern int Fra_FraigSat( Aig_Man_t * pMan, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ); -extern int Fra_FraigCec( Aig_Man_t ** ppAig, int fVerbose ); -extern int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int fVerbose ); -/*=== 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 ); -extern void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose ); -/*=== 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, int nMaxLevs ); -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 int Fra_FraigMiterAssertedOutput( 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, int fProve ); -/*=== 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 nMaxLevs, 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 ); -extern Fra_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ); -extern Fra_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ); -extern void Fra_SmlFreeCounterExample( Fra_Cex_t * p ); -extern int Fra_SmlRunCounterExample( Aig_Man_t * pAig, Fra_Cex_t * p ); -extern Fra_Cex_t * Fra_SmlTrivCounterExample( Aig_Man_t * pAig, int iFrameOut ); - -#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 cf026fac..00000000 --- a/src/aig/fra/fraBmc.c +++ /dev/null @@ -1,422 +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 ); - if ( p->pAigFraig ) - 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, int fKeepPos ) -{ - 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 ); - if ( fKeepPos ) - { - for ( f = 0; f < p->nFramesAll; f++ ) - Aig_ManForEachPoSeq( p->pAig, pObj, i ) - Aig_ObjCreatePo( pAigFrames, Bmc_ObjChild0Frames(pObj,f) ); - Aig_ManCleanup( pAigFrames ); - } - else - { - // 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 = 0, 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, 0 ); - // if implications are present, configure the AIG manager to check them - if ( p->pCla->vImps ) - { - p->pBmc->pAigFrames->pImpFunc = (void (*) (void*, void*))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, 0 ); - 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; -} - -/**Function************************************************************* - - Synopsis [Performs BMC for the given AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose ) -{ - extern Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig ); - Fra_Man_t * pTemp; - Fra_Bmc_t * pBmc; - Aig_Man_t * pAigTemp; - int iOutput; - // derive and fraig the frames - pBmc = Fra_BmcStart( pAig, 0, nFrames ); - pTemp = Fra_LcrAigPrepare( pAig ); - pTemp->pBmc = pBmc; - pBmc->pAigFrames = Fra_BmcFrames( pBmc, 1 ); - if ( fRewrite ) - { - pBmc->pAigFrames = Dar_ManRwsat( pAigTemp = pBmc->pAigFrames, 1, 0 ); - Aig_ManStop( pAigTemp ); - } - iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFrames ); - if ( iOutput >= 0 ) - pAig->pSeqModel = Fra_SmlTrivCounterExample( pAig, iOutput ); - else - { - pBmc->pAigFraig = Fra_FraigEquivence( pBmc->pAigFrames, nBTLimit, 1 ); - iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFraig ); - if ( pBmc->pAigFraig->pData ) - { - pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pBmc->pAigFrames, pBmc->pAigFraig->pData ); - FREE( pBmc->pAigFraig->pData ); - } - else if ( iOutput >= 0 ) - pAig->pSeqModel = Fra_SmlTrivCounterExample( pAig, iOutput ); - } - if ( fVerbose ) - printf( "nFrames = %3d. Aig = %6d. Init frames = %6d. Fraiged init frames = %6d.\n", - nFrames, Aig_ManNodeNum(pAig), Aig_ManNodeNum(pBmc->pAigFrames), pBmc->pAigFraig? Aig_ManNodeNum(pBmc->pAigFraig) : -1 ); - Fra_BmcStop( pBmc ); - free( pTemp ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraCec.c b/src/aig/fra/fraCec.c deleted file mode 100644 index bdab25dd..00000000 --- a/src/aig/fra/fraCec.c +++ /dev/null @@ -1,303 +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" -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigSat( Aig_Man_t * pMan, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ) -{ - sat_solver * pSat; - Cnf_Dat_t * pCnf; - int status, RetValue, clk = clock(); - Vec_Int_t * vCiIds; - - assert( Aig_ManPoNum(pMan) == 1 ); - pMan->pData = NULL; - - // derive CNF - pCnf = Cnf_Derive( pMan, 0 ); -// pCnf = Cnf_DeriveSimple( pMan, 0 ); - // convert into the SAT solver - pSat = Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - vCiIds = Cnf_DataCollectPiSatNums( pCnf, 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 ) - { - pMan->pData = 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 [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigCec( Aig_Man_t ** ppAig, int fVerbose ) -{ - int nBTLimitStart = 300; // starting SAT run - int nBTLimitFirst = 2; // first fraiging iteration - int nBTLimitLast = 1000000; // the last-gasp SAT run - - Fra_Par_t Params, * pParams = &Params; - Aig_Man_t * pAig = *ppAig, * pTemp; - int i, RetValue, clk; - - // report the original miter - if ( fVerbose ) - { - printf( "Original miter: Nodes = %6d.\n", Aig_ManNodeNum(pAig) ); - } - RetValue = Fra_FraigMiterStatus( pAig ); -// assert( RetValue == -1 ); - if ( RetValue >= 0 ) - return RetValue; - - // if SAT only, solve without iteration -clk = clock(); - RetValue = Fra_FraigSat( pAig, (sint64)2*nBTLimitStart, (sint64)0, 0 ); - if ( fVerbose ) - { - printf( "Initial SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); -PRT( "Time", clock() - clk ); - } - if ( RetValue >= 0 ) - return RetValue; - - // duplicate the AIG -clk = clock(); -// pAig = Aig_ManDup( pTemp = pAig ); - pAig = Dar_ManRwsat( pTemp = pAig, 0, 0 ); - Aig_ManStop( pTemp ); - if ( fVerbose ) - { - printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); -PRT( "Time", clock() - clk ); - } - - // perform the loop - Fra_ParamsDefault( pParams ); - pParams->nBTLimitNode = nBTLimitFirst; - pParams->nBTLimitMiter = nBTLimitStart; - pParams->fDontShowBar = 1; - pParams->fProve = 1; - for ( i = 0; i < 6; i++ ) - { -//printf( "Running fraiging with %d BTnode and %d BTmiter.\n", pParams->nBTLimitNode, pParams->nBTLimitMiter ); - // run fraiging -clk = clock(); - pAig = Fra_FraigPerform( pTemp = pAig, pParams ); - Aig_ManStop( pTemp ); - if ( fVerbose ) - { - printf( "Fraiging (i=%d): Nodes = %6d. ", i+1, Aig_ManNodeNum(pAig) ); -PRT( "Time", clock() - clk ); - } - - // check the miter status - RetValue = Fra_FraigMiterStatus( pAig ); - if ( RetValue >= 0 ) - break; - - // perform rewriting -clk = clock(); - pAig = Dar_ManRewriteDefault( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) - { - printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); -PRT( "Time", clock() - clk ); - } - - // check the miter status - RetValue = Fra_FraigMiterStatus( pAig ); - if ( RetValue >= 0 ) - break; - // try simulation - - // set the parameters for the next run - pParams->nBTLimitNode = 8 * pParams->nBTLimitNode; - pParams->nBTLimitMiter = 2 * pParams->nBTLimitMiter; - } - - // if still unsolved try last gasp - if ( RetValue == -1 ) - { -clk = clock(); - RetValue = Fra_FraigSat( pAig, (sint64)nBTLimitLast, (sint64)0, 0 ); - if ( fVerbose ) - { - printf( "Final SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); -PRT( "Time", clock() - clk ); - } - } - - *ppAig = pAig; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int fVerbose ) -{ - Aig_Man_t * pAig; - Vec_Ptr_t * vParts; - int i, RetValue = 1, nOutputs; - // create partitions - vParts = Aig_ManMiterPartitioned( pMan1, pMan2, 100 ); - // solve the partitions - nOutputs = -1; - Vec_PtrForEachEntry( vParts, pAig, i ) - { - nOutputs++; - if ( fVerbose ) - printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", - i+1, Vec_PtrSize(vParts), Aig_ManPiNum(pAig), Aig_ManPoNum(pAig), - Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); - RetValue = Fra_FraigMiterStatus( pAig ); - if ( RetValue == 1 ) - continue; - if ( RetValue == 0 ) - break; - RetValue = Fra_FraigCec( &pAig, 0 ); - Vec_PtrWriteEntry( vParts, i, pAig ); - if ( RetValue == 1 ) - continue; - if ( RetValue == 0 ) - break; - break; - } - // clear the result - if ( fVerbose ) - { - printf( " \r" ); - fflush( stdout ); - } - // report the timeout - if ( RetValue == -1 ) - { - printf( "Timed out after verifying %d partitions (out of %d).\n", nOutputs, Vec_PtrSize(vParts) ); - fflush( stdout ); - } - // free intermediate results - Vec_PtrForEachEntry( vParts, pAig, i ) - Aig_ManStop( pAig ); - Vec_PtrFree( vParts ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraClass.c b/src/aig/fra/fraClass.c deleted file mode 100644 index 2d03e65d..00000000 --- a/src/aig/fra/fraClass.c +++ /dev/null @@ -1,855 +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, int nMaxLevs ) -{ - 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 ( nMaxLevs && (int)pObj->Level >= nMaxLevs ) - 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 - cMinSupp = -1; - 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/fraClau.c b/src/aig/fra/fraClau.c deleted file mode 100644 index fc239a40..00000000 --- a/src/aig/fra/fraClau.c +++ /dev/null @@ -1,759 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraClau.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Induction with clause strengthening.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" -#include "cnf.h" -#include "satSolver.h" - -/* - This code is inspired by the paper: Aaron Bradley and Zohar Manna, - "Checking safety by inductive generalization of counterexamples to - induction", FMCAD '07. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Cla_Man_t_ Cla_Man_t; -struct Cla_Man_t_ -{ - // SAT solvers - sat_solver * pSatMain; - sat_solver * pSatTest; - sat_solver * pSatBmc; - // CNF for the test solver -// Cnf_Dat_t * pCnfTest; - // SAT variables - Vec_Int_t * vSatVarsMainCs; - Vec_Int_t * vSatVarsTestCs; - Vec_Int_t * vSatVarsTestNs; - Vec_Int_t * vSatVarsBmcNs; - // helper variables - int nSatVarsTestBeg; - int nSatVarsTestCur; - // counter-examples - Vec_Int_t * vCexMain0; - Vec_Int_t * vCexMain; - Vec_Int_t * vCexTest; - Vec_Int_t * vCexBase; - Vec_Int_t * vCexAssm; - Vec_Int_t * vCexBmc; - // mapping of CS into NS var numbers - int * pMapCsMainToCsTest; - int * pMapCsTestToCsMain; - int * pMapCsTestToNsTest; - int * pMapCsTestToNsBmc; -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Saves variables corresponding to latch outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Fra_ClauSaveLatchVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int fCsVars ) -{ - Vec_Int_t * vVars; - Aig_Obj_t * pObjLo, * pObjLi; - int i; - vVars = Vec_IntAlloc( Aig_ManRegNum(pMan) ); - Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) - Vec_IntPush( vVars, pCnf->pVarNums[fCsVars? pObjLo->Id : pObjLi->Id] ); - return vVars; -} - -/**Function************************************************************* - - Synopsis [Saves variables corresponding to latch outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Fra_ClauSaveOutputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf ) -{ - Vec_Int_t * vVars; - Aig_Obj_t * pObj; - int i; - vVars = Vec_IntAlloc( Aig_ManPoNum(pMan) ); - Aig_ManForEachPo( pMan, pObj, i ) - Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] ); - return vVars; -} - -/**Function************************************************************* - - Synopsis [Saves variables corresponding to latch outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Fra_ClauSaveInputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int nStarting ) -{ - Vec_Int_t * vVars; - Aig_Obj_t * pObj; - int i; - vVars = Vec_IntAlloc( Aig_ManPiNum(pMan) - nStarting ); - Aig_ManForEachPi( pMan, pObj, i ) - { - if ( i < nStarting ) - continue; - Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] ); - } - return vVars; -} - -/**Function************************************************************* - - Synopsis [Saves variables corresponding to latch outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Fra_ClauCreateMapping( Vec_Int_t * vSatVarsFrom, Vec_Int_t * vSatVarsTo, int nVarsMax ) -{ - int * pMapping, Var, i; - assert( Vec_IntSize(vSatVarsFrom) == Vec_IntSize(vSatVarsTo) ); - pMapping = ALLOC( int, nVarsMax ); - for ( i = 0; i < nVarsMax; i++ ) - pMapping[i] = -1; - Vec_IntForEachEntry( vSatVarsFrom, Var, i ) - pMapping[Var] = Vec_IntEntry(vSatVarsTo,i); - return pMapping; -} - - -/**Function************************************************************* - - Synopsis [Deletes the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClauStop( Cla_Man_t * p ) -{ - free( p->pMapCsMainToCsTest ); - free( p->pMapCsTestToCsMain ); - free( p->pMapCsTestToNsTest ); - free( p->pMapCsTestToNsBmc ); - Vec_IntFree( p->vSatVarsMainCs ); - Vec_IntFree( p->vSatVarsTestCs ); - Vec_IntFree( p->vSatVarsTestNs ); - Vec_IntFree( p->vSatVarsBmcNs ); - Vec_IntFree( p->vCexMain0 ); - Vec_IntFree( p->vCexMain ); - Vec_IntFree( p->vCexTest ); - Vec_IntFree( p->vCexBase ); - Vec_IntFree( p->vCexAssm ); - Vec_IntFree( p->vCexBmc ); - if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); - if ( p->pSatTest ) sat_solver_delete( p->pSatTest ); - if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Takes the AIG with the single output to be checked.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cla_Man_t * Fra_ClauStart( Aig_Man_t * pMan ) -{ - Cla_Man_t * p; - Cnf_Dat_t * pCnfMain; - Cnf_Dat_t * pCnfTest; - Cnf_Dat_t * pCnfBmc; - Aig_Man_t * pFramesMain; - Aig_Man_t * pFramesTest; - Aig_Man_t * pFramesBmc; - assert( Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) == 1 ); - - // start the manager - p = ALLOC( Cla_Man_t, 1 ); - memset( p, 0, sizeof(Cla_Man_t) ); - p->vCexMain0 = Vec_IntAlloc( Aig_ManRegNum(pMan) ); - p->vCexMain = Vec_IntAlloc( Aig_ManRegNum(pMan) ); - p->vCexTest = Vec_IntAlloc( Aig_ManRegNum(pMan) ); - p->vCexBase = Vec_IntAlloc( Aig_ManRegNum(pMan) ); - p->vCexAssm = Vec_IntAlloc( Aig_ManRegNum(pMan) ); - p->vCexBmc = Vec_IntAlloc( Aig_ManRegNum(pMan) ); - - // derive two timeframes to be checked - pFramesMain = Aig_ManFrames( pMan, 2, 0, 1, 0, 0, NULL ); // nFrames, fInit, fOuts, fRegs -//Aig_ManShow( pFramesMain, 0, NULL ); - assert( Aig_ManPoNum(pFramesMain) == 2 ); - Aig_ObjChild0Flip( Aig_ManPo(pFramesMain, 0) ); // complement the first output - pCnfMain = Cnf_DeriveSimple( pFramesMain, 0 ); -//Cnf_DataWriteIntoFile( pCnfMain, "temp.cnf", 1 ); - p->pSatMain = Cnf_DataWriteIntoSolver( pCnfMain, 1, 0 ); -/* - { - int i; - Aig_Obj_t * pObj; - Aig_ManForEachObj( pFramesMain, pObj, i ) - printf( "%d -> %d \n", pObj->Id, pCnfMain->pVarNums[pObj->Id] ); - printf( "\n" ); - } -*/ - - // derive one timeframe to be checked - pFramesTest = Aig_ManFrames( pMan, 1, 0, 0, 1, 0, NULL ); - assert( Aig_ManPoNum(pFramesTest) == Aig_ManRegNum(pMan) ); - pCnfTest = Cnf_DeriveSimple( pFramesTest, Aig_ManRegNum(pMan) ); - p->pSatTest = Cnf_DataWriteIntoSolver( pCnfTest, 1, 0 ); - p->nSatVarsTestBeg = p->nSatVarsTestCur = sat_solver_nvars( p->pSatTest ); - - // derive one timeframe to be checked for BMC - pFramesBmc = Aig_ManFrames( pMan, 1, 1, 0, 1, 0, NULL ); -//Aig_ManShow( pFramesBmc, 0, NULL ); - assert( Aig_ManPoNum(pFramesBmc) == Aig_ManRegNum(pMan) ); - pCnfBmc = Cnf_DeriveSimple( pFramesBmc, Aig_ManRegNum(pMan) ); - p->pSatBmc = Cnf_DataWriteIntoSolver( pCnfBmc, 1, 0 ); - - // create variable sets - p->vSatVarsMainCs = Fra_ClauSaveInputVars( pFramesMain, pCnfMain, 2 * (Aig_ManPiNum(pMan)-Aig_ManRegNum(pMan)) ); - p->vSatVarsTestCs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 1 ); - p->vSatVarsTestNs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 0 ); - p->vSatVarsBmcNs = Fra_ClauSaveOutputVars( pFramesBmc, pCnfBmc ); - assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsMainCs) ); - assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsBmcNs) ); - - // create mapping of CS into NS vars - p->pMapCsMainToCsTest = Fra_ClauCreateMapping( p->vSatVarsMainCs, p->vSatVarsTestCs, Aig_ManObjNumMax(pFramesMain) ); - p->pMapCsTestToCsMain = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsMainCs, Aig_ManObjNumMax(pFramesTest) ); - p->pMapCsTestToNsTest = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsTestNs, Aig_ManObjNumMax(pFramesTest) ); - p->pMapCsTestToNsBmc = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsBmcNs, Aig_ManObjNumMax(pFramesTest) ); - - // cleanup - Cnf_DataFree( pCnfMain ); - Cnf_DataFree( pCnfTest ); - Cnf_DataFree( pCnfBmc ); - Aig_ManStop( pFramesMain ); - Aig_ManStop( pFramesTest ); - Aig_ManStop( pFramesBmc ); - if ( p->pSatMain == NULL || p->pSatTest == NULL || p->pSatBmc == NULL ) - { - Fra_ClauStop( p ); - return NULL; - } - return p; -} - -/**Function************************************************************* - - Synopsis [Splits off second half and returns it as a new vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Vec_Int_t * Vec_IntSplitHalf( Vec_Int_t * vVec ) -{ - Vec_Int_t * vPart; - int Entry, i; - assert( Vec_IntSize(vVec) > 1 ); - vPart = Vec_IntAlloc( Vec_IntSize(vVec) / 2 + 1 ); - Vec_IntForEachEntryStart( vVec, Entry, i, Vec_IntSize(vVec) / 2 ) - Vec_IntPush( vPart, Entry ); - Vec_IntShrink( vVec, Vec_IntSize(vVec) / 2 ); - return vPart; -} - -/**Function************************************************************* - - Synopsis [Appends the contents of the second vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 ) -{ - int Entry, i; - Vec_IntForEachEntry( vVec2, Entry, i ) - Vec_IntPush( vVec1, Entry ); -} - -/**Function************************************************************* - - Synopsis [Complements all literals in the clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Vec_IntComplement( Vec_Int_t * vVec ) -{ - int i; - for ( i = 0; i < Vec_IntSize(vVec); i++ ) - vVec->pArray[i] = lit_neg( vVec->pArray[i] ); -} - -/**Function************************************************************* - - Synopsis [Checks if the property holds. Returns counter-example if not.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClauCheckProperty( Cla_Man_t * p, Vec_Int_t * vCex ) -{ - int nBTLimit = 0; - int RetValue, iVar, i; - sat_solver_act_var_clear( p->pSatMain ); - RetValue = sat_solver_solve( p->pSatMain, NULL, NULL, (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - Vec_IntClear( vCex ); - if ( RetValue == l_False ) - return 1; - assert( RetValue == l_True ); - Vec_IntForEachEntry( p->vSatVarsMainCs, iVar, i ) - Vec_IntPush( vCex, sat_solver_var_literal(p->pSatMain, iVar) ); -/* - { - int i; - for (i = 0; i < p->pSatMain->size; i++) - printf( "%d=%d ", i, p->pSatMain->model.ptr[i] == l_True ); - printf( "\n" ); - } -*/ - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks if the clause holds using BMC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClauCheckBmc( Cla_Man_t * p, Vec_Int_t * vClause ) -{ - int nBTLimit = 0; - int RetValue; - RetValue = sat_solver_solve( p->pSatBmc, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause), - (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - if ( RetValue == l_False ) - return 1; - assert( RetValue == l_True ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Lifts the clause to depend on NS variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClauRemapClause( int * pMap, Vec_Int_t * vClause, Vec_Int_t * vRemapped, int fInv ) -{ - int iLit, i; - Vec_IntClear( vRemapped ); - Vec_IntForEachEntry( vClause, iLit, i ) - { - assert( pMap[lit_var(iLit)] >= 0 ); - iLit = toLitCond( pMap[lit_var(iLit)], lit_sign(iLit) ^ fInv ); - Vec_IntPush( vRemapped, iLit ); - } -} - -/**Function************************************************************* - - Synopsis [Checks if the clause holds. Returns counter example if not.] - - Description [Uses test SAT solver.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClauCheckClause( Cla_Man_t * p, Vec_Int_t * vClause, Vec_Int_t * vCex ) -{ - int nBTLimit = 0; - int RetValue, iVar, i; - int nClauseSize = Vec_IntSize( vClause ); - // complement literals - Vec_IntPush( vClause, toLit( p->nSatVarsTestCur++ ) ); // helper positive - Vec_IntComplement( vClause ); // helper negative (the clause is C v h') - // add the clause - RetValue = sat_solver_addclause( p->pSatTest, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) ); - assert( RetValue == 1 ); - // complement all literals - Vec_IntPop( vClause ); // helper removed - Vec_IntComplement( vClause ); - // create the assumption in terms of NS variables - Fra_ClauRemapClause( p->pMapCsTestToNsTest, vClause, p->vCexAssm, 0 ); - // add helper literals - for ( i = p->nSatVarsTestBeg; i < p->nSatVarsTestCur - 1; i++ ) - Vec_IntPush( p->vCexAssm, toLitCond(i,1) ); // other helpers negative - Vec_IntPush( p->vCexAssm, toLitCond(i,0) ); // positive helper - // try to solve - RetValue = sat_solver_solve( p->pSatTest, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm), - (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - if ( vCex ) - Vec_IntClear( vCex ); - if ( RetValue == l_False ) - return 1; - assert( RetValue == l_True ); - if ( vCex ) - { - Vec_IntForEachEntry( p->vSatVarsTestCs, iVar, i ) - Vec_IntPush( vCex, sat_solver_var_literal(p->pSatTest, iVar) ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Reduces the counter-example by removing complemented literals.] - - Description [Removes literals from vMain that differ from those in the - counter-example (vNew). Relies on the fact that the PI variables are - assigned in the increasing order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClauReduceClause( Vec_Int_t * vMain, Vec_Int_t * vNew ) -{ - int LitM, LitN, VarM, VarN, i, j, k; - assert( Vec_IntSize(vMain) <= Vec_IntSize(vNew) ); - for ( i = j = k = 0; i < Vec_IntSize(vMain) && j < Vec_IntSize(vNew); ) - { - LitM = Vec_IntEntry( vMain, i ); - LitN = Vec_IntEntry( vNew, j ); - VarM = lit_var( LitM ); - VarN = lit_var( LitN ); - if ( VarM < VarN ) - { - assert( 0 ); - } - else if ( VarM > VarN ) - { - j++; - } - else // if ( VarM == VarN ) - { - i++; - j++; - if ( LitM == LitN ) - Vec_IntWriteEntry( vMain, k++, LitM ); - } - } - assert( i == Vec_IntSize(vMain) ); - Vec_IntShrink( vMain, k ); -} - -/**Function************************************************************* - - Synopsis [Computes the minimal invariant that holds.] - - Description [On entrace, vBasis does not hold, vBasis+vExtra holds but - is not minimal. On exit, vBasis is unchanged, vBasis+vExtra is minimal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClauMinimizeClause_rec( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra ) -{ - Vec_Int_t * vExtra2; - int nSizeOld; - if ( Vec_IntSize(vExtra) == 1 ) - return; - nSizeOld = Vec_IntSize( vBasis ); - vExtra2 = Vec_IntSplitHalf( vExtra ); - - // try the first half - Vec_IntAppend( vBasis, vExtra ); - if ( Fra_ClauCheckClause( p, vBasis, NULL ) ) - { - Vec_IntShrink( vBasis, nSizeOld ); - Fra_ClauMinimizeClause_rec( p, vBasis, vExtra ); - return; - } - Vec_IntShrink( vBasis, nSizeOld ); - - // try the second half - Vec_IntAppend( vBasis, vExtra2 ); - if ( Fra_ClauCheckClause( p, vBasis, NULL ) ) - { - Vec_IntShrink( vBasis, nSizeOld ); - Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 ); - return; - } -// Vec_IntShrink( vBasis, nSizeOld ); - - // find the smallest with the second half added - Fra_ClauMinimizeClause_rec( p, vBasis, vExtra ); - Vec_IntShrink( vBasis, nSizeOld ); - Vec_IntAppend( vBasis, vExtra ); - // find the smallest with the second half added - Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 ); - Vec_IntShrink( vBasis, nSizeOld ); - Vec_IntAppend( vExtra, vExtra2 ); - Vec_IntFree( vExtra2 ); -} - -/**Function************************************************************* - - Synopsis [Minimizes the clauses using a simple method.] - - Description [The input and output clause are in vExtra.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClauMinimizeClause( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra ) -{ - int iLit, iLit2, i, k; - Vec_IntForEachEntryReverse( vExtra, iLit, i ) - { - // copy literals without the given one - Vec_IntClear( vBasis ); - Vec_IntForEachEntry( vExtra, iLit2, k ) - if ( k != i ) - Vec_IntPush( vBasis, iLit2 ); - // try whether it is inductive - if ( !Fra_ClauCheckClause( p, vBasis, NULL ) ) - continue; - // the clause is inductive - // remove the literal - for ( k = i; k < Vec_IntSize(vExtra)-1; k++ ) - Vec_IntWriteEntry( vExtra, k, Vec_IntEntry(vExtra,k+1) ); - Vec_IntShrink( vExtra, Vec_IntSize(vExtra)-1 ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClauPrintClause( Vec_Int_t * vSatCsVars, Vec_Int_t * vCex ) -{ - int LitM, VarM, VarN, i, j, k; - assert( Vec_IntSize(vCex) <= Vec_IntSize(vSatCsVars) ); - for ( i = j = k = 0; i < Vec_IntSize(vCex) && j < Vec_IntSize(vSatCsVars); ) - { - LitM = Vec_IntEntry( vCex, i ); - VarM = lit_var( LitM ); - VarN = Vec_IntEntry( vSatCsVars, j ); - if ( VarM < VarN ) - { - assert( 0 ); - } - else if ( VarM > VarN ) - { - j++; - printf( "-" ); - } - else // if ( VarM == VarN ) - { - i++; - j++; - printf( "%d", !lit_sign(LitM) ); - } - } - assert( i == Vec_IntSize(vCex) ); -} - -/**Function************************************************************* - - Synopsis [Takes the AIG with the single output to be checked.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose ) -{ - Cla_Man_t * p; - int Iter, RetValue, fFailed, i; - assert( Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) == 1 ); - // create the manager - p = Fra_ClauStart( pMan ); - if ( p == NULL ) - { - printf( "The property is trivially inductive.\n" ); - return 1; - } - // generate counter-examples and expand them - for ( Iter = 0; !Fra_ClauCheckProperty( p, p->vCexMain0 ) && Iter < nIters; Iter++ ) - { - if ( fVerbose ) - printf( "%4d : ", Iter ); - // remap clause into the test manager - Fra_ClauRemapClause( p->pMapCsMainToCsTest, p->vCexMain0, p->vCexMain, 0 ); - if ( fVerbose && fVeryVerbose ) - Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); - // the main counter-example is in p->vCexMain - // intermediate counter-examples are in p->vCexTest - // generate the reduced counter-example to the inductive property - fFailed = 0; - for ( i = 0; !Fra_ClauCheckClause( p, p->vCexMain, p->vCexTest ); i++ ) - { - Fra_ClauReduceClause( p->vCexMain, p->vCexTest ); - Fra_ClauRemapClause( p->pMapCsTestToNsBmc, p->vCexMain, p->vCexBmc, 0 ); - -// if ( !Fra_ClauCheckBmc(p, p->vCexBmc) ) - if ( Vec_IntSize(p->vCexMain) < 1 ) - { - Vec_IntComplement( p->vCexMain0 ); - RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexMain0), Vec_IntArray(p->vCexMain0) + Vec_IntSize(p->vCexMain0) ); - if ( RetValue == 0 ) - { - printf( "\nProperty is proved after %d iterations.\n", Iter+1 ); - return 0; - } - fFailed = 1; - break; - } - } - if ( fFailed ) - { - if ( fVerbose ) - printf( " Reducing failed after %d iterations (BMC failed).\n", i ); - continue; - } - if ( Vec_IntSize(p->vCexMain) == 0 ) - { - if ( fVerbose ) - printf( " Reducing failed after %d iterations (nothing left).\n", i ); - continue; - } - if ( fVerbose ) - printf( " " ); - if ( fVerbose && fVeryVerbose ) - Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); - if ( fVerbose ) - printf( " LitsInd = %3d. ", Vec_IntSize(p->vCexMain) ); - // minimize the inductive property - Vec_IntClear( p->vCexBase ); - if ( Vec_IntSize(p->vCexMain) > 1 ) -// Fra_ClauMinimizeClause_rec( p, p->vCexBase, p->vCexMain ); - Fra_ClauMinimizeClause( p, p->vCexBase, p->vCexMain ); - assert( Vec_IntSize(p->vCexMain) > 0 ); - if ( fVerbose && fVeryVerbose ) - Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); - if ( fVerbose ) - printf( " LitsRed = %3d. ", Vec_IntSize(p->vCexMain) ); - if ( fVerbose ) - printf( "\n" ); - // add the clause to the solver - Fra_ClauRemapClause( p->pMapCsTestToCsMain, p->vCexMain, p->vCexAssm, 1 ); - RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm) ); - if ( RetValue == 0 ) - { - Iter++; - break; - } - if ( p->pSatMain->qtail != p->pSatMain->qhead ) - { - RetValue = sat_solver_simplify(p->pSatMain); - assert( RetValue != 0 ); - assert( p->pSatMain->qtail == p->pSatMain->qhead ); - } - } - - // report the results - if ( Iter == nIters ) - { - printf( "Property is not proved after %d iterations.\n", nIters ); - return 0; - } - printf( "Property is proved after %d iterations.\n", Iter ); - Fra_ClauStop( p ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraClaus.c b/src/aig/fra/fraClaus.c deleted file mode 100644 index 7e8d7dd1..00000000 --- a/src/aig/fra/fraClaus.c +++ /dev/null @@ -1,1561 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraClaus.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Induction with clause strengthening.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" -#include "cnf.h" -#include "satSolver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Clu_Man_t_ Clu_Man_t; -struct Clu_Man_t_ -{ - // parameters - int nFrames; // the K of the K-step induction - int nPref; // the number of timeframes to skip - int nClausesMax; // the max number of 4-clauses to consider - int nLutSize; // the max cut size - int nLevels; // the number of levels for cut computation - int nCutsMax; // the maximum number of cuts to compute at a node - int nBatches; // the number of clause batches to use - int fStepUp; // increase cut size for each batch - int fVerbose; - int fVeryVerbose; - // internal parameters - int nSimWords; // the number of simulation words - int nSimWordsPref; // the number of simulation words in the prefix - int nSimFrames; // the number of frames to simulate - int nBTLimit; // the largest number of backtracks (0 = infinite) - // the network - Aig_Man_t * pAig; - // SAT solvers - sat_solver * pSatMain; - sat_solver * pSatBmc; - // CNF for the test solver - Cnf_Dat_t * pCnf; - int fFail; - int fFiltering; - int fNothingNew; - // clauses - Vec_Int_t * vLits; - Vec_Int_t * vClauses; - Vec_Int_t * vCosts; - int nClauses; - // clauses proven - Vec_Int_t * vLitsProven; - Vec_Int_t * vClausesProven; - int nClausesProven; - // counter-examples - Vec_Ptr_t * vCexes; - int nCexes; - int nCexesAlloc; -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Runs the SAT solver on the problem.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausRunBmc( Clu_Man_t * p ) -{ - Aig_Obj_t * pObj; - int Lits[2], nLitsTot, RetValue, i; - // set the output literals - nLitsTot = 2 * p->pCnf->nVars; - pObj = Aig_ManPo(p->pAig, 0); - for ( i = 0; i < p->nPref + p->nFrames; i++ ) - { - Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 0 ); - RetValue = sat_solver_solve( p->pSatBmc, Lits, Lits + 1, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - if ( RetValue != l_False ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Runs the SAT solver on the problem.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausRunSat( Clu_Man_t * p ) -{ - Aig_Obj_t * pObj; - int * pLits; - int i, RetValue; - pLits = ALLOC( int, p->nFrames + 1 ); - // set the output literals - pObj = Aig_ManPo(p->pAig, 0); - for ( i = 0; i <= p->nFrames; i++ ) - pLits[i] = i * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObj->Id], i != p->nFrames ); - // try to solve the problem - RetValue = sat_solver_solve( p->pSatMain, pLits, pLits + p->nFrames + 1, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - free( pLits ); - if ( RetValue == l_False ) - return 1; - // get the counter-example - assert( RetValue == l_True ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Runs the SAT solver on the problem.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausRunSat0( Clu_Man_t * p ) -{ - Aig_Obj_t * pObj; - int Lits[2], RetValue; - pObj = Aig_ManPo(p->pAig, 0); - Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 0 ); - RetValue = sat_solver_solve( p->pSatMain, Lits, Lits + 1, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - if ( RetValue == l_False ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Return combinations appearing in the cut.] - - Description [This procedure is taken from "Hacker's Delight" by H.S.Warren.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void transpose32a( unsigned a[32] ) -{ - int j, k; - unsigned long m, t; - for ( j = 16, m = 0x0000FFFF; j; j >>= 1, m ^= m << j ) - { - for ( k = 0; k < 32; k = ((k | j) + 1) & ~j ) - { - t = (a[k] ^ (a[k|j] >> j)) & m; - a[k] ^= t; - a[k|j] ^= (t << j); - } - } -} - -/**Function************************************************************* - - Synopsis [Return combinations appearing in the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausProcessClausesCut( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores ) -{ - unsigned Matrix[32]; - unsigned * pSims[16], uWord; - int nSeries, i, k, j; - int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; - // compute parameters - assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 ); - assert( nWordsForSim % 8 == 0 ); - // get parameters - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref; - // add combinational patterns - memset( pScores, 0, sizeof(int) * 16 ); - nSeries = nWordsForSim / 8; - for ( i = 0; i < nSeries; i++ ) - { - memset( Matrix, 0, sizeof(unsigned) * 32 ); - for ( k = 0; k < 8; k++ ) - for ( j = 0; j < (int)pCut->nLeaves; j++ ) - Matrix[31-(k*4+j)] = pSims[j][i*8+k]; - transpose32a( Matrix ); - for ( k = 0; k < 32; k++ ) - for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 ) - pScores[uWord & 0xF]++; - } - // collect patterns - uWord = 0; - for ( i = 0; i < 16; i++ ) - if ( pScores[i] ) - uWord |= (1 << i); -// Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" ); - return (int)uWord; -} - -/**Function************************************************************* - - Synopsis [Return combinations appearing in the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausProcessClausesCut2( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores ) -{ - unsigned * pSims[16], uWord; - int iMint, i, k, b; - int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; - // compute parameters - assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 ); - assert( nWordsForSim % 8 == 0 ); - // get parameters - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref; - // add combinational patterns - memset( pScores, 0, sizeof(int) * 16 ); - for ( i = 0; i < nWordsForSim; i++ ) - for ( k = 0; k < 32; k++ ) - { - iMint = 0; - for ( b = 0; b < (int)pCut->nLeaves; b++ ) - if ( pSims[b][i] & (1 << k) ) - iMint |= (1 << b); - pScores[iMint]++; - } - // collect patterns - uWord = 0; - for ( i = 0; i < 16; i++ ) - if ( pScores[i] ) - uWord |= (1 << i); -// Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" ); - return (int)uWord; -} - -/**Function************************************************************* - - Synopsis [Return the number of combinations appearing in the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausProcessClausesCut3( Clu_Man_t * p, Fra_Sml_t * pSimMan, Aig_Cut_t * pCut, int * pScores ) -{ - unsigned * pSims[16]; - int iMint, i, k, b, nMints; - int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; - // compute parameters - assert( pCut->nFanins > 1 && pCut->nFanins < 17 ); - assert( nWordsForSim % 8 == 0 ); - // get parameters - for ( i = 0; i < (int)pCut->nFanins; i++ ) - pSims[i] = Fra_ObjSim( pSimMan, pCut->pFanins[i] ) + p->nSimWordsPref; - // add combinational patterns - nMints = (1 << pCut->nFanins); - memset( pScores, 0, sizeof(int) * nMints ); - // go through the simulation patterns - for ( i = 0; i < nWordsForSim; i++ ) - for ( k = 0; k < 32; k++ ) - { - iMint = 0; - for ( b = 0; b < (int)pCut->nFanins; b++ ) - if ( pSims[b][i] & (1 << k) ) - iMint |= (1 << b); - pScores[iMint]++; - } -} - - -/**Function************************************************************* - - Synopsis [Returns the cut-off cost.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausSelectClauses( Clu_Man_t * p ) -{ - int * pCostCount, nClauCount, Cost, CostMax, i, c; - assert( Vec_IntSize(p->vClauses) > p->nClausesMax ); - // count how many implications have each cost - CostMax = p->nSimWords * 32 + 1; - pCostCount = ALLOC( int, CostMax ); - memset( pCostCount, 0, sizeof(int) * CostMax ); - Vec_IntForEachEntry( p->vCosts, Cost, i ) - { - if ( Cost == -1 ) - continue; - assert( Cost < CostMax ); - pCostCount[ Cost ]++; - } - assert( pCostCount[0] == 0 ); - // select the bound on the cost (above this bound, implication will be included) - nClauCount = 0; - for ( c = CostMax - 1; c > 0; c-- ) - { - assert( pCostCount[c] >= 0 ); - nClauCount += pCostCount[c]; - if ( nClauCount >= p->nClausesMax ) - break; - } - // collect implications with the given costs - nClauCount = 0; - Vec_IntForEachEntry( p->vCosts, Cost, i ) - { - if ( Cost >= c && nClauCount < p->nClausesMax ) - { - nClauCount++; - continue; - } - Vec_IntWriteEntry( p->vCosts, i, -1 ); - } - free( pCostCount ); - p->nClauses = nClauCount; -if ( p->fVerbose ) -printf( "Selected %d clauses. Cost range: [%d < %d < %d]\n", nClauCount, 1, c, CostMax ); - return c; -} - - -/**Function************************************************************* - - Synopsis [Processes the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausRecordClause( Clu_Man_t * p, Dar_Cut_t * pCut, int iMint, int Cost ) -{ - int i; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pLeaves[i]], (iMint&(1<vClauses, Vec_IntSize(p->vLits) ); - Vec_IntPush( p->vCosts, Cost ); -} - -/**Function************************************************************* - - Synopsis [Processes the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausRecordClause2( Clu_Man_t * p, Aig_Cut_t * pCut, int iMint, int Cost ) -{ - int i; - for ( i = 0; i < (int)pCut->nFanins; i++ ) - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pFanins[i]], (iMint&(1<vClauses, Vec_IntSize(p->vLits) ); - Vec_IntPush( p->vCosts, Cost ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausSmlNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i; - pSims = Fra_ObjSim(pSeq, pObj->Id); - for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ ) - if ( pSims[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if implications holds.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausSmlNodesAreImp( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) -{ - unsigned * pSimL, * pSimR; - int k; - pSimL = Fra_ObjSim(pSeq, pObj1->Id); - pSimR = Fra_ObjSim(pSeq, pObj2->Id); - for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) - if ( pSimL[k] & ~pSimR[k] ) // !(Obj1 -> Obj2) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if implications holds.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausSmlNodesAreImpC( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) -{ - unsigned * pSimL, * pSimR; - int k; - pSimL = Fra_ObjSim(pSeq, pObj1->Id); - pSimR = Fra_ObjSim(pSeq, pObj2->Id); - for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) - if ( pSimL[k] & pSimR[k] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Processes the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausCollectLatchClauses( Clu_Man_t * p, Fra_Sml_t * pSeq ) -{ - Aig_Obj_t * pObj1, * pObj2; - unsigned * pSims1, * pSims2; - int CostMax, i, k, nCountConst, nCountImps; - - nCountConst = nCountImps = 0; - CostMax = p->nSimWords * 32; - pSeq->nWordsPref = p->nSimWordsPref; - Aig_ManForEachLoSeq( p->pAig, pObj1, i ) - { - pSims1 = Fra_ObjSim( pSeq, pObj1->Id ); - if ( Fra_ClausSmlNodeIsConst( pSeq, pObj1 ) ) - { - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); - Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); - Vec_IntPush( p->vCosts, CostMax ); - nCountConst++; - continue; - } - Aig_ManForEachLoSeq( p->pAig, pObj2, k ) - { - pSims2 = Fra_ObjSim( pSeq, pObj2->Id ); - if ( Fra_ClausSmlNodesAreImp( pSeq, pObj1, pObj2 ) ) - { - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 0 ) ); - Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); - Vec_IntPush( p->vCosts, CostMax ); - nCountImps++; - continue; - } - if ( Fra_ClausSmlNodesAreImp( pSeq, pObj2, pObj1 ) ) - { - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) ); - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 0 ) ); - Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); - Vec_IntPush( p->vCosts, CostMax ); - nCountImps++; - continue; - } - if ( Fra_ClausSmlNodesAreImpC( pSeq, pObj1, pObj2 ) ) - { - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); - Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) ); - Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); - Vec_IntPush( p->vCosts, CostMax ); - nCountImps++; - continue; - } - } - if ( nCountConst + nCountImps > p->nClausesMax / 2 ) - break; - } - pSeq->nWordsPref = 0; - if ( p->fVerbose ) - printf( "Collected %d constants and %d implications.\n", nCountConst, nCountImps ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Processes the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausProcessClauses( Clu_Man_t * p, int fRefs ) -{ - Aig_MmFixed_t * pMemCuts; -// Aig_ManCut_t * pManCut; - Fra_Sml_t * pComb, * pSeq; - Aig_Obj_t * pObj; - Dar_Cut_t * pCut; - int Scores[16], uScores, i, k, j, clk, nCuts = 0; - - // simulate the AIG -clk = clock(); - srand( 0xAABBAABB ); - pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames ); - if ( pSeq->fNonConstOut ) - { - printf( "Property failed after sequential simulation!\n" ); - Fra_SmlStop( pSeq ); - return 0; - } -if ( p->fVerbose ) -{ -PRT( "Sim-seq", clock() - clk ); -} - - -clk = clock(); - if ( fRefs ) - { - Fra_ClausCollectLatchClauses( p, pSeq ); -if ( p->fVerbose ) -{ -PRT( "Lat-cla", clock() - clk ); -} - } - - - // generate cuts for all nodes, assign cost, and find best cuts -clk = clock(); - pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 1 ); -// pManCut = Aig_ComputeCuts( p->pAig, 10, 4, 0, 1 ); -if ( p->fVerbose ) -{ -PRT( "Cuts ", clock() - clk ); -} - - // collect sequential info for each cut -clk = clock(); - Aig_ManForEachNode( p->pAig, pObj, i ) - Dar_ObjForEachCut( pObj, pCut, k ) - if ( pCut->nLeaves > 1 ) - { - pCut->uTruth = Fra_ClausProcessClausesCut( p, pSeq, pCut, Scores ); -// uScores = Fra_ClausProcessClausesCut2( p, pSeq, pCut, Scores ); -// if ( uScores != pCut->uTruth ) -// { -// int x = 0; -// } - } -if ( p->fVerbose ) -{ -PRT( "Infoseq", clock() - clk ); -} - Fra_SmlStop( pSeq ); - - // perform combinational simulation -clk = clock(); - srand( 0xAABBAABB ); - pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref ); -if ( p->fVerbose ) -{ -PRT( "Sim-cmb", clock() - clk ); -} - - // collect combinational info for each cut -clk = clock(); - Aig_ManForEachNode( p->pAig, pObj, i ) - Dar_ObjForEachCut( pObj, pCut, k ) - if ( pCut->nLeaves > 1 ) - { - nCuts++; - uScores = Fra_ClausProcessClausesCut( p, pComb, pCut, Scores ); - uScores &= ~pCut->uTruth; pCut->uTruth = 0; - if ( uScores == 0 ) - continue; - // write the clauses - for ( j = 0; j < (1<nLeaves); j++ ) - if ( uScores & (1 << j) ) - Fra_ClausRecordClause( p, pCut, j, Scores[j] ); - - } - Fra_SmlStop( pComb ); - Aig_MmFixedStop( pMemCuts, 0 ); -// Aig_ManCutStop( pManCut ); -if ( p->fVerbose ) -{ -PRT( "Infocmb", clock() - clk ); -} - - if ( p->fVerbose ) - printf( "Node = %5d. Non-triv cuts = %7d. Clauses = %6d. Clause per cut = %6.2f.\n", - Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts ); - - if ( Vec_IntSize(p->vClauses) > p->nClausesMax ) - Fra_ClausSelectClauses( p ); - else - p->nClauses = Vec_IntSize( p->vClauses ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Processes the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausProcessClauses2( Clu_Man_t * p, int fRefs ) -{ -// Aig_MmFixed_t * pMemCuts; - Aig_ManCut_t * pManCut; - Fra_Sml_t * pComb, * pSeq; - Aig_Obj_t * pObj; - Aig_Cut_t * pCut; - int i, k, j, clk, nCuts = 0; - int ScoresSeq[1<<12], ScoresComb[1<<12]; - assert( p->nLutSize < 13 ); - - // simulate the AIG -clk = clock(); - srand( 0xAABBAABB ); - pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames ); - if ( pSeq->fNonConstOut ) - { - printf( "Property failed after sequential simulation!\n" ); - Fra_SmlStop( pSeq ); - return 0; - } -if ( p->fVerbose ) -{ -PRT( "Sim-seq", clock() - clk ); -} - - // perform combinational simulation -clk = clock(); - srand( 0xAABBAABB ); - pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref ); -if ( p->fVerbose ) -{ -PRT( "Sim-cmb", clock() - clk ); -} - - -clk = clock(); - if ( fRefs ) - { - Fra_ClausCollectLatchClauses( p, pSeq ); -if ( p->fVerbose ) -{ -PRT( "Lat-cla", clock() - clk ); -} - } - - - // generate cuts for all nodes, assign cost, and find best cuts -clk = clock(); -// pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 1 ); - pManCut = Aig_ComputeCuts( p->pAig, p->nCutsMax, p->nLutSize, 0, p->fVerbose ); -if ( p->fVerbose ) -{ -PRT( "Cuts ", clock() - clk ); -} - - // collect combinational info for each cut -clk = clock(); - Aig_ManForEachNode( p->pAig, pObj, i ) - { - if ( pObj->Level > (unsigned)p->nLevels ) - continue; - Aig_ObjForEachCut( pManCut, pObj, pCut, k ) - if ( pCut->nFanins > 1 ) - { - nCuts++; - Fra_ClausProcessClausesCut3( p, pSeq, pCut, ScoresSeq ); - Fra_ClausProcessClausesCut3( p, pComb, pCut, ScoresComb ); - // write the clauses - for ( j = 0; j < (1<nFanins); j++ ) - if ( ScoresComb[j] != 0 && ScoresSeq[j] == 0 ) - Fra_ClausRecordClause2( p, pCut, j, ScoresComb[j] ); - - } - } - Fra_SmlStop( pSeq ); - Fra_SmlStop( pComb ); -// Aig_MmFixedStop( pMemCuts, 0 ); - Aig_ManCutStop( pManCut ); - p->pAig->pManCuts = NULL; -if ( p->fVerbose ) -{ -PRT( "Infosim", clock() - clk ); -} - - if ( p->fVerbose ) - printf( "Node = %5d. Non-triv cuts = %7d. Clauses = %6d. Clause per cut = %6.2f.\n", - Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts ); - - // filter out clauses that are contained in the already proven clauses - assert( p->nClauses == 0 ); - p->nClauses = Vec_IntSize( p->vClauses ); - if ( Vec_IntSize( p->vClausesProven ) > 0 ) - { - int RetValue, k, Beg, End, * pStart; - // reset the solver - if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); - p->pSatMain = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); - if ( p->pSatMain == NULL ) - { - printf( "Error: Main solver is unsat.\n" ); - return -1; - } - - // add the proven clauses - Beg = 0; - pStart = Vec_IntArray(p->vLitsProven); - Vec_IntForEachEntry( p->vClausesProven, End, i ) - { - assert( End - Beg <= p->nLutSize ); - // add the clause to all timeframes - RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); - if ( RetValue == 0 ) - { - printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); - return -1; - } - Beg = End; - } - assert( End == Vec_IntSize(p->vLitsProven) ); - - // check the clauses - Beg = 0; - pStart = Vec_IntArray(p->vLits); - Vec_IntForEachEntry( p->vClauses, End, i ) - { - assert( Vec_IntEntry( p->vCosts, i ) >= 0 ); - assert( End - Beg <= p->nLutSize ); - // check the clause - for ( k = Beg; k < End; k++ ) - pStart[k] = lit_neg( pStart[k] ); - RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - for ( k = Beg; k < End; k++ ) - pStart[k] = lit_neg( pStart[k] ); - // the clause holds - if ( RetValue == l_False ) - { - Vec_IntWriteEntry( p->vCosts, i, -1 ); - p->nClauses--; - } - Beg = End; - } - assert( End == Vec_IntSize(p->vLits) ); - if ( p->fVerbose ) - printf( "Already proved clauses filtered out %d candidate clauses (out of %d).\n", - Vec_IntSize(p->vClauses) - p->nClauses, Vec_IntSize(p->vClauses) ); - } - - p->fFiltering = 0; - if ( p->nClauses > p->nClausesMax ) - { - Fra_ClausSelectClauses( p ); - p->fFiltering = 1; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausBmcClauses( Clu_Man_t * p ) -{ - int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f; -/* - for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) - printf( "%d ", p->vLits->pArray[i] ); - printf( "\n" ); -*/ - // add the clauses - Counter = 0; - // skip through the prefix variables - if ( p->nPref ) - { - nLitsTot = p->nPref * 2 * p->pCnf->nVars; - for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) - p->vLits->pArray[i] += nLitsTot; - } - // go through the timeframes - nLitsTot = 2 * p->pCnf->nVars; - pStart = Vec_IntArray(p->vLits); - for ( f = 0; f < p->nFrames; f++ ) - { - Beg = 0; - Vec_IntForEachEntry( p->vClauses, End, i ) - { - if ( Vec_IntEntry( p->vCosts, i ) == -1 ) - { - Beg = End; - continue; - } - assert( Vec_IntEntry( p->vCosts, i ) > 0 ); - assert( End - Beg <= p->nLutSize ); - - for ( k = Beg; k < End; k++ ) - pStart[k] = lit_neg( pStart[k] ); - RetValue = sat_solver_solve( p->pSatBmc, pStart + Beg, pStart + End, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - for ( k = Beg; k < End; k++ ) - pStart[k] = lit_neg( pStart[k] ); - - if ( RetValue != l_False ) - { - Beg = End; - Vec_IntWriteEntry( p->vCosts, i, -1 ); - Counter++; - continue; - } -/* - // add the clause - RetValue = sat_solver_addclause( p->pSatBmc, pStart + Beg, pStart + End ); - // assert( RetValue == 1 ); - if ( RetValue == 0 ) - { - printf( "Error: Solver is UNSAT after adding BMC clauses.\n" ); - return -1; - } -*/ - Beg = End; - - // simplify the solver - if ( p->pSatBmc->qtail != p->pSatBmc->qhead ) - { - RetValue = sat_solver_simplify(p->pSatBmc); - assert( RetValue != 0 ); - assert( p->pSatBmc->qtail == p->pSatBmc->qhead ); - } - } - // increment literals - for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) - p->vLits->pArray[i] += nLitsTot; - } - - // return clauses back to normal - nLitsTot = (p->nPref + p->nFrames) * nLitsTot; - for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) - p->vLits->pArray[i] -= nLitsTot; -/* - for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) - printf( "%d ", p->vLits->pArray[i] ); - printf( "\n" ); -*/ - return Counter; -} - -/**Function************************************************************* - - Synopsis [Cleans simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausSimInfoClean( Clu_Man_t * p ) -{ - assert( p->pCnf->nVars <= Vec_PtrSize(p->vCexes) ); - Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 ); - p->nCexes = 0; -} - -/**Function************************************************************* - - Synopsis [Reallocs simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausSimInfoRealloc( Clu_Man_t * p ) -{ - assert( p->nCexes == p->nCexesAlloc ); - Vec_PtrReallocSimInfo( p->vCexes ); - Vec_PtrCleanSimInfo( p->vCexes, p->nCexesAlloc/32, 2 * p->nCexesAlloc/32 ); - p->nCexesAlloc *= 2; -} - -/**Function************************************************************* - - Synopsis [Records simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausSimInfoRecord( Clu_Man_t * p, int * pModel ) -{ - int i; - if ( p->nCexes == p->nCexesAlloc ) - Fra_ClausSimInfoRealloc( p ); - assert( p->nCexes < p->nCexesAlloc ); - for ( i = 0; i < p->pCnf->nVars; i++ ) - { - if ( pModel[i] == l_True ) - { - assert( Aig_InfoHasBit( Vec_PtrEntry(p->vCexes, i), p->nCexes ) == 0 ); - Aig_InfoSetBit( Vec_PtrEntry(p->vCexes, i), p->nCexes ); - } - } - p->nCexes++; -} - -/**Function************************************************************* - - Synopsis [Uses the simulation info.] - - Description [Returns 1 if the simulation info disproved the clause.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausSimInfoCheck( Clu_Man_t * p, int * pLits, int nLits ) -{ - unsigned * pSims[16], uWord; - int nWords, iVar, i, w; - for ( i = 0; i < nLits; i++ ) - { - iVar = lit_var(pLits[i]) - p->nFrames * p->pCnf->nVars; - assert( iVar > 0 && iVar < p->pCnf->nVars ); - pSims[i] = Vec_PtrEntry( p->vCexes, iVar ); - } - nWords = p->nCexes / 32; - for ( w = 0; w < nWords; w++ ) - { - uWord = ~(unsigned)0; - for ( i = 0; i < nLits; i++ ) - uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]); - if ( uWord ) - return 1; - } - if ( p->nCexes % 32 ) - { - uWord = ~(unsigned)0; - for ( i = 0; i < nLits; i++ ) - uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]); - if ( uWord & Aig_InfoMask( p->nCexes % 32 ) ) - return 1; - } - return 0; -} - - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClausInductiveClauses( Clu_Man_t * p ) -{ -// Aig_Obj_t * pObjLi, * pObjLo; - int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f, fFlag;//, Lits[2]; - p->fFail = 0; - - // reset the solver - if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); - p->pSatMain = Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 ); - if ( p->pSatMain == NULL ) - { - printf( "Error: Main solver is unsat.\n" ); - return -1; - } - Fra_ClausSimInfoClean( p ); - -/* - // check if the property holds - if ( Fra_ClausRunSat0( p ) ) - printf( "Property holds without strengthening.\n" ); - else - printf( "Property does not hold without strengthening.\n" ); -*/ -/* - // add constant registers - Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) - if ( Aig_ObjFanin0(pObjLi) == Aig_ManConst1(p->pAig) ) - { - for ( k = 0; k < p->nFrames; k++ ) - { - Lits[0] = k * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObjLo->Id], Aig_ObjFaninC0(pObjLi) ); - RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 ); - if ( RetValue == 0 ) - { - printf( "Error: Solver is UNSAT after adding constant-register clauses.\n" ); - return -1; - } - } - } -*/ - - - // add the proven clauses - nLitsTot = 2 * p->pCnf->nVars; - pStart = Vec_IntArray(p->vLitsProven); - for ( f = 0; f < p->nFrames; f++ ) - { - Beg = 0; - Vec_IntForEachEntry( p->vClausesProven, End, i ) - { - assert( End - Beg <= p->nLutSize ); - // add the clause to all timeframes - RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); - if ( RetValue == 0 ) - { - printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); - return -1; - } - Beg = End; - } - // increment literals - for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ ) - p->vLitsProven->pArray[i] += nLitsTot; - } - // return clauses back to normal - nLitsTot = (p->nFrames) * nLitsTot; - for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ ) - p->vLitsProven->pArray[i] -= nLitsTot; - -/* - // add the proven clauses - nLitsTot = 2 * p->pCnf->nVars; - pStart = Vec_IntArray(p->vLitsProven); - Beg = 0; - Vec_IntForEachEntry( p->vClausesProven, End, i ) - { - assert( End - Beg <= p->nLutSize ); - // add the clause to all timeframes - RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); - if ( RetValue == 0 ) - { - printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); - return -1; - } - Beg = End; - } -*/ - - // add the clauses - nLitsTot = 2 * p->pCnf->nVars; - pStart = Vec_IntArray(p->vLits); - for ( f = 0; f < p->nFrames; f++ ) - { - Beg = 0; - Vec_IntForEachEntry( p->vClauses, End, i ) - { - if ( Vec_IntEntry( p->vCosts, i ) == -1 ) - { - Beg = End; - continue; - } - assert( Vec_IntEntry( p->vCosts, i ) > 0 ); - assert( End - Beg <= p->nLutSize ); - // add the clause to all timeframes - RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); - if ( RetValue == 0 ) - { - printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); - return -1; - } - Beg = End; - } - // increment literals - for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) - p->vLits->pArray[i] += nLitsTot; - } - - // simplify the solver - if ( p->pSatMain->qtail != p->pSatMain->qhead ) - { - RetValue = sat_solver_simplify(p->pSatMain); - assert( RetValue != 0 ); - assert( p->pSatMain->qtail == p->pSatMain->qhead ); - } - - // check if the property holds - if ( Fra_ClausRunSat0( p ) ) - { - if ( p->fVerbose ) - printf( " Property holds. " ); - } - else - { - if ( p->fVerbose ) - printf( " Property fails. " ); -// return -2; - p->fFail = 1; - } - -/* - // add the property for the first K frames - for ( i = 0; i < p->nFrames; i++ ) - { - Aig_Obj_t * pObj; - int Lits[2]; - // set the output literals - pObj = Aig_ManPo(p->pAig, 0); - Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 1 ); - // add the clause - RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 ); -// assert( RetValue == 1 ); - if ( RetValue == 0 ) - { - printf( "Error: Solver is UNSAT after adding property for the first K frames.\n" ); - return -1; - } - } -*/ - - // simplify the solver - if ( p->pSatMain->qtail != p->pSatMain->qhead ) - { - RetValue = sat_solver_simplify(p->pSatMain); - assert( RetValue != 0 ); - assert( p->pSatMain->qtail == p->pSatMain->qhead ); - } - - - // check the clause in the last timeframe - Beg = 0; - Counter = 0; - Vec_IntForEachEntry( p->vClauses, End, i ) - { - if ( Vec_IntEntry( p->vCosts, i ) == -1 ) - { - Beg = End; - continue; - } - assert( Vec_IntEntry( p->vCosts, i ) > 0 ); - assert( End - Beg <= p->nLutSize ); - - if ( Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg) ) - { - fFlag = 1; -// printf( "s-" ); - - Beg = End; - Vec_IntWriteEntry( p->vCosts, i, -1 ); - Counter++; - continue; - } - else - { - fFlag = 0; -// printf( "s?" ); - } - - for ( k = Beg; k < End; k++ ) - pStart[k] = lit_neg( pStart[k] ); - RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (sint64)p->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); - for ( k = Beg; k < End; k++ ) - pStart[k] = lit_neg( pStart[k] ); - - // the problem is not solved - if ( RetValue != l_False ) - { -// printf( "S- " ); - Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model.ptr + p->nFrames * p->pCnf->nVars ); -// RetValue = Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg); -// assert( RetValue ); - - Beg = End; - Vec_IntWriteEntry( p->vCosts, i, -1 ); - Counter++; - continue; - } -// printf( "S+ " ); -// assert( !fFlag ); - -/* - // add the clause - RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); -// assert( RetValue == 1 ); - if ( RetValue == 0 ) - { - printf( "Error: Solver is UNSAT after adding proved clauses.\n" ); - return -1; - } -*/ - Beg = End; - - // simplify the solver - if ( p->pSatMain->qtail != p->pSatMain->qhead ) - { - RetValue = sat_solver_simplify(p->pSatMain); - assert( RetValue != 0 ); - assert( p->pSatMain->qtail == p->pSatMain->qhead ); - } - } - - // return clauses back to normal - nLitsTot = p->nFrames * nLitsTot; - for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) - p->vLits->pArray[i] -= nLitsTot; - -// if ( fFail ) -// return -2; - return Counter; -} - - - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Clu_Man_t * Fra_ClausAlloc( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fVerbose, int fVeryVerbose ) -{ - Clu_Man_t * p; - p = ALLOC( Clu_Man_t, 1 ); - memset( p, 0, sizeof(Clu_Man_t) ); - p->pAig = pAig; - p->nFrames = nFrames; - p->nPref = nPref; - p->nClausesMax = nClausesMax; - p->nLutSize = nLutSize; - p->nLevels = nLevels; - p->nCutsMax = nCutsMax; - p->nBatches = nBatches; - p->fStepUp = fStepUp; - p->fVerbose = fVerbose; - p->fVeryVerbose = fVeryVerbose; - p->nSimWords = 512;//1024;//64; - p->nSimFrames = 32;//8;//32; - p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames; - - p->vLits = Vec_IntAlloc( 1<<14 ); - p->vClauses = Vec_IntAlloc( 1<<12 ); - p->vCosts = Vec_IntAlloc( 1<<12 ); - - p->vLitsProven = Vec_IntAlloc( 1<<14 ); - p->vClausesProven= Vec_IntAlloc( 1<<12 ); - - p->nCexesAlloc = 1024; - p->vCexes = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pAig)+1, p->nCexesAlloc/32 ); - Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausFree( Clu_Man_t * p ) -{ - if ( p->vCexes ) Vec_PtrFree( p->vCexes ); - if ( p->vLits ) Vec_IntFree( p->vLits ); - if ( p->vClauses ) Vec_IntFree( p->vClauses ); - if ( p->vLitsProven ) Vec_IntFree( p->vLitsProven ); - if ( p->vClausesProven ) Vec_IntFree( p->vClausesProven ); - if ( p->vCosts ) Vec_IntFree( p->vCosts ); - if ( p->pCnf ) Cnf_DataFree( p->pCnf ); - if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); - if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc ); - free( p ); -} - - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausAddToStorage( Clu_Man_t * p ) -{ - int * pStart; - int Beg, End, Counter, i, k; - Beg = 0; - Counter = 0; - pStart = Vec_IntArray( p->vLits ); - Vec_IntForEachEntry( p->vClauses, End, i ) - { - if ( Vec_IntEntry( p->vCosts, i ) == -1 ) - { - Beg = End; - continue; - } - assert( Vec_IntEntry( p->vCosts, i ) > 0 ); - assert( End - Beg <= p->nLutSize ); - for ( k = Beg; k < End; k++ ) - Vec_IntPush( p->vLitsProven, pStart[k] ); - Vec_IntPush( p->vClausesProven, Vec_IntSize(p->vLitsProven) ); - Beg = End; - Counter++; - } - if ( p->fVerbose ) - printf( "Added to storage %d proved clauses\n", Counter ); - - Vec_IntClear( p->vClauses ); - Vec_IntClear( p->vLits ); - Vec_IntClear( p->vCosts ); - p->nClauses = 0; - - p->fNothingNew = (int)(Counter == 0); -} - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fVerbose, int fVeryVerbose ) -{ - Clu_Man_t * p; - int clk, clkTotal = clock(); - int b, Iter, Counter, nPrefOld; - - assert( Aig_ManPoNum(pAig) - Aig_ManRegNum(pAig) == 1 ); - - // create the manager - p = Fra_ClausAlloc( pAig, nFrames, nPref, nClausesMax, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fVerbose, fVeryVerbose ); - -clk = clock(); - // derive CNF - p->pAig->nRegs++; - p->pCnf = Cnf_DeriveSimple( p->pAig, Aig_ManPoNum(p->pAig) ); - p->pAig->nRegs--; -if ( fVerbose ) -{ -PRT( "CNF ", clock() - clk ); -} - - // check BMC -clk = clock(); - p->pSatBmc = Cnf_DataWriteIntoSolver( p->pCnf, p->nPref + p->nFrames, 1 ); - if ( p->pSatBmc == NULL ) - { - printf( "Error: BMC solver is unsat.\n" ); - Fra_ClausFree( p ); - return 1; - } - if ( !Fra_ClausRunBmc( p ) ) - { - printf( "Problem fails the base case after %d frame expansion.\n", p->nPref + p->nFrames ); - Fra_ClausFree( p ); - return 1; - } -if ( fVerbose ) -{ -PRT( "SAT-bmc", clock() - clk ); -} - - // start the SAT solver -clk = clock(); - p->pSatMain = Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 ); - if ( p->pSatMain == NULL ) - { - printf( "Error: Main solver is unsat.\n" ); - Fra_ClausFree( p ); - return 1; - } - - - for ( b = 0; b < p->nBatches; b++ ) - { -// if ( fVerbose ) - printf( "*** BATCH %d: ", b+1 ); - if ( b && (!p->fFiltering || p->fNothingNew || p->fStepUp) ) - p->nLutSize++; - printf( "Using %d-cuts.\n", p->nLutSize ); - - // try solving without additional clauses - if ( Fra_ClausRunSat( p ) ) - { - printf( "Problem is inductive without strengthening.\n" ); - Fra_ClausFree( p ); - return 1; - } - if ( fVerbose ) - { - PRT( "SAT-ind", clock() - clk ); - } - - // collect the candidate inductive clauses using 4-cuts - clk = clock(); - nPrefOld = p->nPref; p->nPref = 0; p->nSimWordsPref = 0; - // Fra_ClausProcessClauses( p, fRefs ); - Fra_ClausProcessClauses2( p, fRefs ); - p->nPref = nPrefOld; - p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames; - - //PRT( "Clauses", clock() - clk ); - - - // check clauses using BMC - if ( fBmc ) - { - clk = clock(); - Counter = Fra_ClausBmcClauses( p ); - p->nClauses -= Counter; - if ( fVerbose ) - { - printf( "BMC disproved %d clauses.\n", Counter ); - PRT( "Cla-bmc", clock() - clk ); - } - } - - - // prove clauses inductively - clk = clock(); - Counter = 1; - for ( Iter = 0; Counter > 0; Iter++ ) - { - if ( fVerbose ) - printf( "Iter %3d : Begin = %5d. ", Iter, p->nClauses ); - Counter = Fra_ClausInductiveClauses( p ); - if ( Counter > 0 ) - p->nClauses -= Counter; - if ( fVerbose ) - { - printf( "End = %5d. Exs = %5d. ", p->nClauses, p->nCexes ); - // printf( "\n" ); - PRT( "Time", clock() - clk ); - } - clk = clock(); - } - if ( Counter == -1 ) - printf( "Fra_Claus(): Internal error. " ); - else if ( p->fFail ) - printf( "Property FAILS during refinement. " ); - else - printf( "Property HOLDS inductively after strengthening. " ); - PRT( "Time ", clock() - clkTotal ); - - if ( !p->fFail ) - break; - - // add proved clauses to storage - Fra_ClausAddToStorage( p ); - } - - // clean the manager - Fra_ClausFree( p ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraCnf.c b/src/aig/fra/fraCnf.c deleted file mode 100644 index d96fe8a1..00000000 --- a/src/aig/fra/fraCnf.c +++ /dev/null @@ -1,284 +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 ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Fra_ObjSatNum(pObj) ) - return; - assert( Fra_ObjSatNum(pObj) == 0 ); - assert( Fra_ObjFaninVec(pObj) == NULL ); - if ( Aig_ObjIsConst1(pObj) ) - return; - 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 95d65e25..00000000 --- a/src/aig/fra/fraCore.c +++ /dev/null @@ -1,466 +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, * pChild; - int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; - if ( p->pData ) - return 0; - Aig_ManForEachPoSeq( p, pObj, i ) - { - pChild = Aig_ObjChild0(pObj); - // check if the output is constant 0 - if ( pChild == Aig_ManConst0(p) ) - { - CountConst0++; - continue; - } - // check if the output is constant 1 - if ( pChild == Aig_ManConst1(p) ) - { - CountNonConst0++; - continue; - } - // check if the output can be not constant 0 - if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) - { - 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 [Reports the status of the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigMiterAssertedOutput( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pChild; - int i; - Aig_ManForEachPoSeq( p, pObj, i ) - { - pChild = Aig_ObjChild0(pObj); - // check if the output is constant 0 - if ( pChild == Aig_ManConst0(p) ) - continue; - // check if the output is constant 1 - if ( pChild == Aig_ManConst1(p) ) - return i; - // check if the output can be not constant 0 - if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) - return i; - } - 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->pManFraig->pData ) - return; - 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 = NULL; - Aig_Obj_t * pObj, * pObjNew; - int i, 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 -// if ( !p->pPars->fDontShowBar ) -// pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pManAig) ); - Aig_ManForEachNode( p->pManAig, pObj, i ) - { -// if ( pProgress ) -// 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 ); - } -// if ( pProgress ) -// 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; - pPars->fDontShowBar = 1; - return Fra_FraigPerform( pManAig, pPars ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve ) -{ - 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 = fProve; - pPars->fVerbose = 0; - pPars->fDontShowBar = 1; - 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 e2bee834..00000000 --- a/src/aig/fra/fraImp.c +++ /dev/null @@ -1,723 +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-- ) - { - // HERE WE ARE MISSING SOME POTENTIAL IMPLICATIONS (with complement!) - - 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 1c2140bb..00000000 --- a/src/aig/fra/fraInd.c +++ /dev/null @@ -1,484 +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 = Dar_ManRwsat( pTemp, 1, 0 ); - pTemp = Dar_ManRewriteDefault( p->pManFraig ); -// 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 nMaxLevs, 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->nMaxLevs = nMaxLevs; - 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, p->pPars->nMaxLevs ); -// 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, 1, 0 ); - 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. ", Aig_ManNodeNum(p->pManFraig) ); - printf( "\n" ); - } - - // perform sweeping - p->nSatCallsRecent = 0; - p->nSatCallsSkipped = 0; -clk2 = clock(); - Fra_FraigSweep( p ); - if ( fVerbose ) - { -// PRT( "t", clock() - clk2 ); - } - -// 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 a6460ed7..00000000 --- a/src/aig/fra/fraLcr.c +++ /dev/null @@ -1,656 +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 ) - Aig_ManForEachObj( 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[(long)pObj0->pNext]; - nPart1 = pLcr->pInToOutPart[(long)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[(long)pObj0->pNext] ); - pOut1 = Aig_ManPo( pFraig, pLcr->pInToOutNum[(long)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[(long)pObj->pNext]; - pFraig = Vec_PtrEntry( pLcr->vFraigs, nPart ); - // get the fraig outputs - pOut = Aig_ManPo( pFraig, pLcr->pInToOutNum[(long)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 *)(long)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+(long)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+(long)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[(long)ppClass[c]->pNext] = i; - pInToOutNum[(long)ppClass[c]->pNext] = Vec_IntSize(vOneNew); - Vec_IntPush( vOneNew, Offset+(long)ppClass[c]->pNext ); - } - } - else - { - pObjPi = Vec_PtrEntry( pCla->vClasses1, Out - Vec_PtrSize(pCla->vClasses) ); - pInToOutPart[(long)pObjPi->pNext] = i; - pInToOutNum[(long)pObjPi->pNext] = Vec_IntSize(vOneNew); - Vec_IntPush( vOneNew, Offset+(long)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+(long)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+(long)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+(long)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+(long)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; - 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 ) - { - pAig->pSeqModel = Fra_SmlGetCounterExample( pSml ); - 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, 0 ); - 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, 0 ); -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 f4964746..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 819605d6..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 c6bdc20e..00000000 --- a/src/aig/fra/fraSec.c +++ /dev/null @@ -1,290 +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, 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, 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 ); - p->pSeqModel = pTemp->pSeqModel; pTemp->pSeqModel = NULL; - 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, 0 ); - 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, 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( pTemp = pNew ); - Aig_ManStop( pTemp ); - if ( fVerbose ) - { - printf( "Rewriting: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - - // perform retiming -// if ( fRetimeFirst && pNew->nRegs ) - 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 - if ( pNew->nRegs ) - { -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 ) - { - p->pSeqModel = Fra_SmlGetCounterExample( pSml ); - 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, 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 1ad2d4f7..00000000 --- a/src/aig/fra/fraSim.c +++ /dev/null @@ -1,1066 +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 * pObjPo ) -{ - Aig_Obj_t * pFanin, * pObjPi; - unsigned * pSims; - int i, k, BestPat, * pModel; - // find the word of the pattern - pFanin = Aig_ObjFanin0(pObjPo); - pSims = Fra_ObjSim(p->pSml, pFanin->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)+1 ); - Aig_ManForEachPi( p->pManAig, pObjPi, i ) - { - pModel[i] = Aig_InfoHasBit(Fra_ObjSim(p->pSml, pObjPi->Id), BestPat); -// printf( "%d", pModel[i] ); - } - pModel[Aig_ManPiNum(p->pManAig)] = pObjPo->Id; -// 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, 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 ); - if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) - return; - Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, 0 ); -// 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; -} - -/**Function************************************************************* - - Synopsis [Resimulates the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlRunCounterExample( Aig_Man_t * pAig, Fra_Cex_t * p ) -{ - Fra_Sml_t * pSml; - Aig_Obj_t * pObj; - int RetValue, i, k, iBit; - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManRegNum(pAig) < Aig_ManPiNum(pAig) ); - // start a new sequential simulator - pSml = Fra_SmlStart( pAig, 0, p->iFrame+1, 1 ); - // assign simulation info for the registers - iBit = 0; - Aig_ManForEachLoSeq( pAig, pObj, i ) - Fra_SmlAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), 0 ); - // assign simulation info for the primary inputs - for ( i = 0; i <= p->iFrame; i++ ) - Aig_ManForEachPiSeq( pAig, pObj, k ) - Fra_SmlAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), i ); - assert( iBit == p->nBits ); - // run random simulation - Fra_SmlSimulateOne( pSml ); - // check if the given output has failed - RetValue = !Fra_SmlNodeIsZero( pSml, Aig_ManPo(pAig, p->iPo) ); - Fra_SmlStop( pSml ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Allocates a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Cex_t * Fra_SmlAllocCounterExample( int nRegs, int nRealPis, int nFrames ) -{ - Fra_Cex_t * pCex; - int nWords = Aig_BitWordNum( nRegs + nRealPis * nFrames ); - pCex = (Fra_Cex_t *)malloc( sizeof(Fra_Cex_t) + sizeof(unsigned) * nWords ); - memset( pCex, 0, sizeof(Fra_Cex_t) + sizeof(unsigned) * nWords ); - pCex->nRegs = nRegs; - pCex->nPis = nRealPis; - pCex->nBits = nRegs + nRealPis * nFrames; - return pCex; -} - -/**Function************************************************************* - - Synopsis [Frees the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlFreeCounterExample( Fra_Cex_t * pCex ) -{ - free( pCex ); -} - -/**Function************************************************************* - - Synopsis [Creates sequential counter-example from the simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ) -{ - Fra_Cex_t * pCex; - Aig_Obj_t * pObj; - unsigned * pSims; - int iPo, iFrame, iBit, i, k; - - // make sure the simulation manager has it - assert( p->fNonConstOut ); - - // find the first output that failed - iPo = -1; - iBit = -1; - iFrame = -1; - Aig_ManForEachPoSeq( p->pAig, pObj, iPo ) - { - if ( Fra_SmlNodeIsZero(p, pObj) ) - continue; - pSims = Fra_ObjSim( p, pObj->Id ); - for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) - if ( pSims[i] ) - { - iFrame = i / p->nWordsFrame; - iBit = 32 * (i % p->nWordsFrame) + Aig_WordFindFirstBit( pSims[i] ); - break; - } - break; - } - assert( iPo < Aig_ManPoNum(p->pAig)-Aig_ManRegNum(p->pAig) ); - assert( iFrame < p->nFrames ); - assert( iBit < 32 * p->nWordsFrame ); - - // allocate the counter example - pCex = Fra_SmlAllocCounterExample( Aig_ManRegNum(p->pAig), Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 ); - pCex->iPo = iPo; - pCex->iFrame = iFrame; - - // copy the bit data - Aig_ManForEachLoSeq( p->pAig, pObj, k ) - { - pSims = Fra_ObjSim( p, pObj->Id ); - if ( Aig_InfoHasBit( pSims, iBit ) ) - Aig_InfoSetBit( pCex->pData, k ); - } - for ( i = 0; i <= iFrame; i++ ) - { - Aig_ManForEachPiSeq( p->pAig, pObj, k ) - { - pSims = Fra_ObjSim( p, pObj->Id ); - if ( Aig_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) ) - Aig_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k ); - } - } - // verify the counter example - if ( !Fra_SmlRunCounterExample( p->pAig, pCex ) ) - { - printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); - Fra_SmlFreeCounterExample( pCex ); - pCex = NULL; - } - return pCex; -} - -/**Function************************************************************* - - Synopsis [Generates seq counter-example from the combinational one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ) -{ - Fra_Cex_t * pCex; - Aig_Obj_t * pObj; - int i, nFrames, nTruePis, nTruePos, iPo, iFrame; - // get the number of frames - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManRegNum(pFrames) == 0 ); - nTruePis = Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig); - nTruePos = Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig); - nFrames = Aig_ManPiNum(pFrames) / nTruePis; - assert( nTruePis * nFrames == Aig_ManPiNum(pFrames) ); - assert( nTruePos * nFrames == Aig_ManPoNum(pFrames) ); - // find the PO that failed - iPo = -1; - iFrame = -1; - Aig_ManForEachPo( pFrames, pObj, i ) - if ( pObj->Id == pModel[Aig_ManPiNum(pFrames)] ) - { - iPo = i % nTruePos; - iFrame = i / nTruePos; - break; - } - assert( iPo >= 0 ); - // allocate the counter example - pCex = Fra_SmlAllocCounterExample( Aig_ManRegNum(pAig), nTruePis, iFrame + 1 ); - pCex->iPo = iPo; - pCex->iFrame = iFrame; - - // copy the bit data - for ( i = 0; i < Aig_ManPiNum(pFrames); i++ ) - { - if ( pModel[i] ) - Aig_InfoSetBit( pCex->pData, pCex->nRegs + i ); - if ( pCex->nRegs + i == pCex->nBits - 1 ) - break; - } - - // verify the counter example - if ( !Fra_SmlRunCounterExample( pAig, pCex ) ) - { - printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); - Fra_SmlFreeCounterExample( pCex ); - pCex = NULL; - } - return pCex; - -} - -/**Function************************************************************* - - Synopsis [Make the trivial counter-example for the trivially asserted output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Cex_t * Fra_SmlTrivCounterExample( Aig_Man_t * pAig, int iFrameOut ) -{ - Fra_Cex_t * pCex; - int nTruePis, nTruePos, iPo, iFrame; - assert( Aig_ManRegNum(pAig) > 0 ); - nTruePis = Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig); - nTruePos = Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig); - iPo = iFrameOut % nTruePos; - iFrame = iFrameOut / nTruePos; - // allocate the counter example - pCex = Fra_SmlAllocCounterExample( Aig_ManRegNum(pAig), nTruePis, iFrame + 1 ); - pCex->iPo = iPo; - pCex->iFrame = iFrame; - return pCex; -} - -//////////////////////////////////////////////////////////////////////// -/// 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 ffaca75c..00000000 --- a/src/aig/fra/module.make +++ /dev/null @@ -1,15 +0,0 @@ -SRC += src/aig/fra/fraBmc.c \ - src/aig/fra/fraCec.c \ - src/aig/fra/fraClass.c \ - src/aig/fra/fraClau.c \ - src/aig/fra/fraClaus.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/fraPart.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 af1d9cd3..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 e697a729..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, int fCompact ); -/*=== 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 498cdd30..00000000 --- a/src/aig/ioa/ioaReadAig.c +++ /dev/null @@ -1,366 +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 /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**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)); -} - -/**Function************************************************************* - - Synopsis [Decodes the encoded array of literals.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries ) -{ - Vec_Int_t * vLits; - int Lit, LitPrev, Diff, i; - vLits = Vec_IntAlloc( nEntries ); - LitPrev = Ioa_ReadAigerDecode( ppPos ); - Vec_IntPush( vLits, LitPrev ); - for ( i = 1; i < nEntries; i++ ) - { -// Diff = Lit - LitPrev; -// Diff = (Lit < LitPrev)? -Diff : Diff; -// Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev); - Diff = Ioa_ReadAigerDecode( ppPos ); - Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1; - Lit = Diff + LitPrev; - Vec_IntPush( vLits, Lit ); - LitPrev = Lit; - } - return vLits; -} - - -/**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_Int_t * vLits = NULL; - 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 || (pContents[3] != ' ' && pContents[3] != '2') ) - { - 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; - if ( pContents[3] == ' ' ) // standard AIGER - { - // scroll to the beginning of the binary data - for ( i = 0; i < nLatches + nOutputs; ) - if ( *pCur++ == '\n' ) - i++; - } - else // modified AIGER - { - vLits = Ioa_WriteDecodeLiterals( &pCur, nLatches + nOutputs ); - } - - // 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 ); - if ( pContents[3] == ' ' ) // standard AIGER - { - pCur = pDrivers; - for ( i = 0; i < nLatches; i++ ) - { - uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); - pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); - Vec_PtrPush( vDrivers, pNode0 ); - } - // read the PO driver literals - for ( i = 0; i < nOutputs; i++ ) - { - uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); - pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); - Vec_PtrPush( vDrivers, pNode0 ); - } - - } - else - { - // read the latch driver literals - for ( i = 0; i < nLatches; i++ ) - { - uLit0 = Vec_IntEntry( vLits, i ); - pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); - Vec_PtrPush( vDrivers, pNode0 ); - } - // read the PO driver literals - for ( i = 0; i < nOutputs; i++ ) - { - uLit0 = Vec_IntEntry( vLits, i+nLatches ); - pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); - Vec_PtrPush( vDrivers, pNode0 ); - } - Vec_IntFree( vLits ); - } - - // 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; -} - - -//////////////////////////////////////////////////////////////////////// -/// 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 166dca4b..00000000 --- a/src/aig/ioa/ioaWriteAig.c +++ /dev/null @@ -1,378 +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 int Ioa_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } -static int Ioa_ObjAigerNum( Aig_Obj_t * pObj ) { return pObj->iData; } -static void Ioa_ObjSetAigerNum( Aig_Obj_t * pObj, unsigned Num ) { pObj->iData = Num; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**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; -} - -/**Function************************************************************* - - Synopsis [Create the array of literals to be written.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ioa_WriteAigerLiterals( Aig_Man_t * pMan ) -{ - Vec_Int_t * vLits; - Aig_Obj_t * pObj, * pDriver; - int i; - vLits = Vec_IntAlloc( Aig_ManPoNum(pMan) ); - Aig_ManForEachLiSeq( pMan, pObj, i ) - { - pDriver = Aig_ObjFanin0(pObj); - Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); - } - Aig_ManForEachPoSeq( pMan, pObj, i ) - { - pDriver = Aig_ObjFanin0(pObj); - Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); - } - return vLits; -} - -/**Function************************************************************* - - Synopsis [Creates the binary encoded array of literals.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Str_t * Ioa_WriteEncodeLiterals( Vec_Int_t * vLits ) -{ - Vec_Str_t * vBinary; - int Pos = 0, Lit, LitPrev, Diff, i; - vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) ); - LitPrev = Vec_IntEntry( vLits, 0 ); - Pos = Ioa_WriteAigerEncode( Vec_StrArray(vBinary), Pos, LitPrev ); - Vec_IntForEachEntryStart( vLits, Lit, i, 1 ) - { - Diff = Lit - LitPrev; - Diff = (Lit < LitPrev)? -Diff : Diff; - Diff = (Diff << 1) | (int)(Lit < LitPrev); - Pos = Ioa_WriteAigerEncode( Vec_StrArray(vBinary), Pos, Diff ); - LitPrev = Lit; - if ( Pos + 10 > vBinary->nCap ) - Vec_StrGrow( vBinary, vBinary->nCap+1 ); - } - vBinary->nSize = Pos; -/* - // verify - { - extern Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries ); - char * pPos = Vec_StrArray( vBinary ); - Vec_Int_t * vTemp = Ioa_WriteDecodeLiterals( &pPos, Vec_IntSize(vLits) ); - for ( i = 0; i < Vec_IntSize(vLits); i++ ) - { - int Entry1 = Vec_IntEntry(vLits,i); - int Entry2 = Vec_IntEntry(vTemp,i); - assert( Entry1 == Entry2 ); - } - Vec_IntFree( vTemp ); - } -*/ - return vBinary; -} - -/**Function************************************************************* - - Synopsis [Writes the AIG in the binary AIGER format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ) -{ -// 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%s %u %u %u %u %u\n", - fCompact? "2" : "", - 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 - - if ( !fCompact ) - { - // 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) ) ); - } - } - else - { - Vec_Int_t * vLits = Ioa_WriteAigerLiterals( pMan ); - Vec_Str_t * vBinary = Ioa_WriteEncodeLiterals( vLits ); - fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); - Vec_StrFree( vBinary ); - Vec_IntFree( vLits ); - } - - // write the nodes into the buffer - Pos = 0; - nBufferSize = 6 * Aig_ManNodeNum(pMan) + 100; // skeptically assuming 3 chars per one AIG edge - pBuffer = ALLOC( unsigned 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, (unsigned)(uLit - uLit1) ); - Pos = Ioa_WriteAigerEncode( pBuffer, Pos, (unsigned)(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 on %s\n", Ioa_TimeStamp() ); - fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); - fclose( pFile ); -} - -//////////////////////////////////////////////////////////////////////// -/// 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 c7435a63..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 4079b6ed..00000000 --- a/src/aig/ivy/ivyFraig.c +++ /dev/null @@ -1,2760 +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( "Miter = %d (%3.1f). Rwr = %d (%3.1f). Fraig = %d (%3.1f). Last = %d.\n", - pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, - pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, - pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti, 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 83012a8c..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 = 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/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 f596d9a8..00000000 --- a/src/aig/kit/kitFactor.c +++ /dev/null @@ -1,339 +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, * cSop = &Sop; - Kit_Graph_t * pFForm; - Kit_Edge_t eRoot; -// int nCubes; - - // works for up to 15 variables because division 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/src/aig/kit/kitGraph.c b/src/aig/kit/kitGraph.c deleted file mode 100644 index 80dcbdc0..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 = 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/src/aig/kit/kitHop.c b/src/aig/kit/kitHop.c deleted file mode 100644 index 86ec5a88..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 = 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/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 20ad0651..00000000 --- a/src/aig/kit/kitSop.c +++ /dev/null @@ -1,572 +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 - 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/src/aig/kit/kitTruth.c b/src/aig/kit/kitTruth.c deleted file mode 100644 index dab60132..00000000 --- a/src/aig/kit/kitTruth.c +++ /dev/null @@ -1,1721 +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 /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// 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/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/ntl/module.make b/src/aig/ntl/module.make deleted file mode 100644 index f47108a4..00000000 --- a/src/aig/ntl/module.make +++ /dev/null @@ -1,11 +0,0 @@ -SRC += src/aig/ntl/ntlAig.c \ - src/aig/ntl/ntlCheck.c \ - src/aig/ntl/ntlDfs.c \ - src/aig/ntl/ntlMan.c \ - src/aig/ntl/ntlMap.c \ - src/aig/ntl/ntlObj.c \ - src/aig/ntl/ntlReadBlif.c \ - src/aig/ntl/ntlTable.c \ - src/aig/ntl/ntlTime.c \ - src/aig/ntl/ntlWriteBlif.c - diff --git a/src/aig/ntl/ntl.h b/src/aig/ntl/ntl.h deleted file mode 100644 index dbd8676b..00000000 --- a/src/aig/ntl/ntl.h +++ /dev/null @@ -1,277 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntl.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - 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 __NTL_H__ -#define __NTL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "aig.h" -#include "tim.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ntl_Man_t_ Ntl_Man_t; -typedef struct Ntl_Mod_t_ Ntl_Mod_t; -typedef struct Ntl_Obj_t_ Ntl_Obj_t; -typedef struct Ntl_Net_t_ Ntl_Net_t; -typedef struct Ntl_Lut_t_ Ntl_Lut_t; - -// object types -typedef enum { - NTL_OBJ_NONE, // 0: non-existent object - NTL_OBJ_PI, // 1: primary input - NTL_OBJ_PO, // 2: primary output - NTL_OBJ_LATCH, // 3: latch node - NTL_OBJ_NODE, // 4: logic node - NTL_OBJ_BOX, // 5: white box or black box - NTL_OBJ_VOID // 6: unused object -} Ntl_Type_t; - -struct Ntl_Man_t_ -{ - // models of this design - char * pName; // the name of this design - char * pSpec; // the name of input file - Vec_Ptr_t * vModels; // the array of all models used to represent boxes - // memory managers - Aig_MmFlex_t * pMemObjs; // memory for objects - Aig_MmFlex_t * pMemSops; // memory for SOPs - // extracted representation - Vec_Ptr_t * vCis; // the primary inputs of the extracted part - Vec_Ptr_t * vCos; // the primary outputs of the extracted part - Vec_Ptr_t * vNodes; // the nodes of the abstracted part - Vec_Int_t * vBox1Cos; // the first COs of the boxes - Aig_Man_t * pAig; // the extracted AIG - Tim_Man_t * pManTime; // the timing manager -}; - -struct Ntl_Mod_t_ -{ - // model description - Ntl_Man_t * pMan; // the model manager - char * pName; // the model name - Vec_Ptr_t * vObjs; // the array of all objects - Vec_Ptr_t * vPis; // the array of PI objects - Vec_Ptr_t * vPos; // the array of PO objects - int nObjs[NTL_OBJ_VOID]; // counter of objects of each type - // hashing names into nets - Ntl_Net_t ** pTable; // the hash table of names into nets - int nTableSize; // the allocated table size - int nEntries; // the number of entries in the hash table - // delay information - Vec_Int_t * vDelays; - Vec_Int_t * vArrivals; - Vec_Int_t * vRequireds; - float * pDelayTable; -}; - -struct Ntl_Obj_t_ -{ - Ntl_Mod_t * pModel; // the model - unsigned Type : 3; // object type - unsigned Id : 27; // object ID - unsigned MarkA : 1; // temporary mark - unsigned MarkB : 1; // temporary mark - short nFanins; // the number of fanins - short nFanouts; // the number of fanouts - union { // functionality - Ntl_Mod_t * pImplem; // model (for boxes) - char * pSop; // SOP (for logic nodes) - unsigned LatchId; // init state + register class (for latches) - }; - Ntl_Net_t * pFanio[0]; // fanins/fanouts -}; - -struct Ntl_Net_t_ -{ - Ntl_Obj_t * pDriver; // driver of the net - Ntl_Net_t * pNext; // next net in the hash table - Aig_Obj_t * pFunc; // the AIG representation - char nVisits; // the number of times the net is visited - char fMark; // temporary mark - char pName[0]; // the name of this net -}; - -struct Ntl_Lut_t_ -{ - int Id; // the ID of the root AIG node - int nFanins; // the number of fanins - int * pFanins; // the array of fanins - unsigned * pTruth; // the truth table -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// INLINED FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Ntl_ModelPiNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PI]; } -static inline int Ntl_ModelPoNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PO]; } -static inline int Ntl_ModelNodeNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_NODE]; } -static inline int Ntl_ModelLatchNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_LATCH]; } -static inline int Ntl_ModelBoxNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_BOX]; } -static inline int Ntl_ModelCiNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PI] + p->nObjs[NTL_OBJ_LATCH]; } -static inline int Ntl_ModelCoNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PO] + p->nObjs[NTL_OBJ_LATCH]; } - -static inline Ntl_Obj_t * Ntl_ModelPi( Ntl_Mod_t * p, int i ) { return Vec_PtrEntry(p->vPis, i); } -static inline Ntl_Obj_t * Ntl_ModelPo( Ntl_Mod_t * p, int i ) { return Vec_PtrEntry(p->vPos, i); } - -static inline char * Ntl_ModelPiName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPi(p, i)->pFanio[0]->pName; } -static inline char * Ntl_ModelPoName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPo(p, i)->pFanio[0]->pName; } - -static inline int Ntl_ModelIsBlackBox( Ntl_Mod_t * p ) { return Ntl_ModelPiNum(p) + Ntl_ModelPoNum(p) == Vec_PtrSize(p->vObjs); } - -static inline int Ntl_ObjFaninNum( Ntl_Obj_t * p ) { return p->nFanins; } -static inline int Ntl_ObjFanoutNum( Ntl_Obj_t * p ) { return p->nFanouts; } - -static inline int Ntl_ObjIsPi( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_PI; } -static inline int Ntl_ObjIsPo( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_PO; } -static inline int Ntl_ObjIsNode( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_NODE; } -static inline int Ntl_ObjIsLatch( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_LATCH; } -static inline int Ntl_ObjIsBox( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_BOX; } - -static inline Ntl_Net_t * Ntl_ObjFanin0( Ntl_Obj_t * p ) { return p->pFanio[0]; } -static inline Ntl_Net_t * Ntl_ObjFanout0( Ntl_Obj_t * p ) { return p->pFanio[p->nFanins]; } - -static inline Ntl_Net_t * Ntl_ObjFanin( Ntl_Obj_t * p, int i ) { return p->pFanio[i]; } -static inline Ntl_Net_t * Ntl_ObjFanout( Ntl_Obj_t * p, int i ) { return p->pFanio[p->nFanins+1]; } - -static inline void Ntl_ObjSetFanin( Ntl_Obj_t * p, Ntl_Net_t * pNet, int i ) { p->pFanio[i] = pNet; } -static inline void Ntl_ObjSetFanout( Ntl_Obj_t * p, Ntl_Net_t * pNet, int i ) { p->pFanio[p->nFanins+i] = pNet; pNet->pDriver = p; } - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -#define Ntl_ManForEachModel( p, pNtl, i ) \ - Vec_PtrForEachEntry( p->vModels, pNtl, i ) -#define Ntl_ManForEachCiNet( p, pNtl, i ) \ - Vec_PtrForEachEntry( p->vCis, pNtl, i ) -#define Ntl_ManForEachCoNet( p, pNtl, i ) \ - Vec_PtrForEachEntry( p->vCos, pNtl, i ) -#define Ntl_ManForEachNode( p, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(p->vNodes)) && (((pObj) = Vec_PtrEntry(p->vNodes, i)), 1); i++ ) \ - if ( !Ntl_ObjIsNode(pObj) ) {} else -#define Ntl_ManForEachBox( p, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(p->vNodes)) && (((pObj) = Vec_PtrEntry(p->vNodes, i)), 1); i++ ) \ - if ( !Ntl_ObjIsBox(pObj) ) {} else - -#define Ntl_ModelForEachPi( pNtl, pObj, i ) \ - Vec_PtrForEachEntry( pNtl->vPis, pObj, i ) -#define Ntl_ModelForEachPo( pNtl, pObj, i ) \ - Vec_PtrForEachEntry( pNtl->vPos, pObj, i ) -#define Ntl_ModelForEachObj( pNtl, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \ - if ( pObj == NULL ) {} else -#define Ntl_ModelForEachLatch( pNtl, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \ - if ( !Ntl_ObjIsLatch(pObj) ) {} else -#define Ntl_ModelForEachNode( pNtl, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \ - if ( !Ntl_ObjIsNode(pObj) ) {} else -#define Ntl_ModelForEachBox( pNtl, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \ - if ( !Ntl_ObjIsBox(pObj) ) {} else -#define Ntl_ModelForEachNet( pNtl, pNet, i ) \ - for ( i = 0; i < pNtl->nTableSize; i++ ) \ - for ( pNet = pNtl->pTable[i]; pNet; pNet = pNet->pNext ) - -#define Ntl_ObjForEachFanin( pObj, pFanin, i ) \ - for ( i = 0; (i < (pObj)->nFanins) && ((pFanin) = (pObj)->pFanio[i]); i++ ) -#define Ntl_ObjForEachFanout( pObj, pFanout, i ) \ - for ( i = 0; (i < (pObj)->nFanouts) && ((pFanout) = (pObj)->pFanio[(pObj)->nFanins+i]); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== ntlAig.c ==========================================================*/ -extern Aig_Obj_t * Ntl_ManExtractAigNode( Ntl_Obj_t * pNode ); -extern int Ntl_ManExtract( Ntl_Man_t * p ); -extern int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping ); -extern int Ntl_ManInsertTest( Ntl_Man_t * p ); -extern int Ntl_ManInsertTestFpga( Ntl_Man_t * p ); -extern int Ntl_ManInsertTestIf( Ntl_Man_t * p ); -/*=== ntlCheck.c ==========================================================*/ -extern int Ntl_ManCheck( Ntl_Man_t * pMan ); -extern int Ntl_ModelCheck( Ntl_Mod_t * pModel ); -extern void Ntl_ModelFixNonDrivenNets( Ntl_Mod_t * pModel ); -/*=== ntlDfs.c ==========================================================*/ -extern int Ntl_ManDfs( Ntl_Man_t * p ); -/*=== ntlMan.c ============================================================*/ -extern Ntl_Man_t * Ntl_ManAlloc( char * pFileName ); -extern void Ntl_ManFree( Ntl_Man_t * p ); -extern Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, char * pName ); -extern void Ntl_ManPrintStats( Ntl_Man_t * p ); -extern Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName ); -extern void Ntl_ModelFree( Ntl_Mod_t * p ); -/*=== ntlMap.c ============================================================*/ -extern Vec_Ptr_t * Ntl_MappingAlloc( int nLuts, int nVars ); -extern Vec_Ptr_t * Ntl_MappingFromAig( Aig_Man_t * p ); -extern Vec_Ptr_t * Ntl_MappingFpga( Aig_Man_t * p ); -extern Vec_Ptr_t * Ntl_MappingIf( Ntl_Man_t * pMan, Aig_Man_t * p ); -/*=== ntlObj.c ============================================================*/ -extern Ntl_Obj_t * Ntl_ModelCreatePi( Ntl_Mod_t * pModel ); -extern Ntl_Obj_t * Ntl_ModelCreatePo( Ntl_Mod_t * pModel, Ntl_Net_t * pNet ); -extern Ntl_Obj_t * Ntl_ModelCreateLatch( Ntl_Mod_t * pModel ); -extern Ntl_Obj_t * Ntl_ModelCreateNode( Ntl_Mod_t * pModel, int nFanins ); -extern Ntl_Obj_t * Ntl_ModelCreateBox( Ntl_Mod_t * pModel, int nFanins, int nFanouts ); -extern char * Ntl_ManStoreName( Ntl_Man_t * p, char * pName ); -extern char * Ntl_ManStoreSop( Ntl_Man_t * p, char * pSop ); -extern char * Ntl_ManStoreFileName( Ntl_Man_t * p, char * pFileName ); -/*=== ntlTable.c ==========================================================*/ -extern Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, char * pName ); -extern Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, char * pName ); -extern int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ); -extern int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, char * pName, int * pNumber ); -/*=== ntlTime.c ==========================================================*/ -extern Tim_Man_t * Ntl_ManCreateTiming( Ntl_Man_t * p ); -/*=== ntlReadBlif.c ==========================================================*/ -extern Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck ); -/*=== ntlWriteBlif.c ==========================================================*/ -extern void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/ntl/ntlAig.c b/src/aig/ntl/ntlAig.c deleted file mode 100644 index c0a122d3..00000000 --- a/src/aig/ntl/ntlAig.c +++ /dev/null @@ -1,596 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlAig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Netlist SOP to AIG conversion.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "dec.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Ntl_SopForEachCube( pSop, nFanins, pCube ) \ - for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) -#define Ntl_CubeForEachVar( pCube, Value, i ) \ - for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks if the cover is constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_SopIsConst0( char * pSop ) -{ - return pSop[0] == ' ' && pSop[1] == '0'; -} - -/**Function************************************************************* - - Synopsis [Reads the number of variables in the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_SopGetVarNum( char * pSop ) -{ - char * pCur; - for ( pCur = pSop; *pCur != '\n'; pCur++ ); - return pCur - pSop - 2; -} - -/**Function************************************************************* - - Synopsis [Reads the number of cubes in the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_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 [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_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 [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_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 [Creates the constant 1 cover with the given number of variables and cubes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ntl_SopStart( Aig_MmFlex_t * pMan, int nCubes, int nVars ) -{ - char * pSopCover, * pCube; - int i, Length; - - Length = nCubes * (nVars + 3); - pSopCover = Aig_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 cover from the ISOP computed from TT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ntl_SopCreateFromIsop( Aig_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 = Ntl_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 [Transforms truth table into the SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ntl_SopFromTruth( Ntl_Man_t * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ) -{ - char * pSop; - int RetValue; - if ( Kit_TruthIsConst0(pTruth, nVars) ) - return Ntl_ManStoreSop( p, " 0\n" ); - if ( Kit_TruthIsConst1(pTruth, nVars) ) - return Ntl_ManStoreSop( p, " 1\n" ); - RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); // 1 ); - assert( RetValue == 0 || RetValue == 1 ); - pSop = Ntl_SopCreateFromIsop( p->pMemSops, nVars, vCover ); - if ( RetValue ) - Ntl_SopComplement( pSop ); - return pSop; -} - - - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ntl_ConvertSopToAigInternal( Aig_Man_t * pMan, Ntl_Obj_t * pNode, char * pSop ) -{ - Ntl_Net_t * pNet; - Aig_Obj_t * pAnd, * pSum; - int i, Value, nFanins; - char * pCube; - // get the number of variables - nFanins = Ntl_SopGetVarNum(pSop); - // go through the cubes of the node's SOP - pSum = Aig_ManConst0(pMan); - Ntl_SopForEachCube( pSop, nFanins, pCube ) - { - // create the AND of literals - pAnd = Aig_ManConst1(pMan); - Ntl_CubeForEachVar( pCube, Value, i ) - { - pNet = Ntl_ObjFanin( pNode, i ); - if ( Value == '1' ) - pAnd = Aig_And( pMan, pAnd, pNet->pFunc ); - else if ( Value == '0' ) - pAnd = Aig_And( pMan, pAnd, Aig_Not(pNet->pFunc) ); - } - // add to the sum of cubes - pSum = Aig_Or( pMan, pSum, pAnd ); - } - // decide whether to complement the result - if ( Ntl_SopIsComplement(pSop) ) - pSum = Aig_Not(pSum); - return pSum; -} - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ntl_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph ) -{ - Dec_Node_t * pNode; - Aig_Obj_t * pAnd0, * pAnd1; - int i; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Aig_NotCond( Aig_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Aig_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 = Aig_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Aig_NotCond( Dec_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, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Converts the network from AIG to BDD representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ntl_ManExtractAigNode( Ntl_Obj_t * pNode ) -{ - Aig_Man_t * pMan = pNode->pModel->pMan->pAig; - int fUseFactor = 0; - // consider the constant node - if ( Ntl_SopGetVarNum(pNode->pSop) == 0 ) - return Aig_NotCond( Aig_ManConst1(pMan), Ntl_SopIsConst0(pNode->pSop) ); - // decide when to use factoring - if ( fUseFactor && Ntl_SopGetVarNum(pNode->pSop) > 2 && Ntl_SopGetCubeNum(pNode->pSop) > 1 ) - { - Dec_Graph_t * pFForm; - Dec_Node_t * pFFNode; - Aig_Obj_t * pFunc; - int i; - // perform factoring - pFForm = Dec_Factor( pNode->pSop ); - // collect the fanins - Dec_GraphForEachLeaf( pFForm, pFFNode, i ) - pFFNode->pFunc = Ntl_ObjFanin(pNode, i)->pFunc; - // perform strashing - pFunc = Ntl_GraphToNetworkAig( pMan, pFForm ); - Dec_GraphFree( pFForm ); - return pFunc; - } - return Ntl_ConvertSopToAigInternal( pMan, pNode, pNode->pSop ); -} - - - - -/**Function************************************************************* - - Synopsis [Extracts AIG from the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManExtract_old( Ntl_Man_t * p ) -{ - Ntl_Obj_t * pNode; - Ntl_Net_t * pNet; - int i; - // check the DFS traversal - if ( !Ntl_ManDfs( p ) ) - return 0; - // start the AIG manager - assert( p->pAig == NULL ); - p->pAig = Aig_ManStart( 10000 ); - // create the primary inputs - Ntl_ManForEachCiNet( p, pNet, i ) - pNet->pFunc = Aig_ObjCreatePi( p->pAig ); - // convert internal nodes to AIGs - Ntl_ManForEachNode( p, pNode, i ) - Ntl_ObjFanout0(pNode)->pFunc = Ntl_ManExtractAigNode( pNode ); - // create the primary outputs - Ntl_ManForEachCoNet( p, pNet, i ) - Aig_ObjCreatePo( p->pAig, pNet->pFunc ); - // cleanup the AIG - Aig_ManCleanup( p->pAig ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Extracts AIG from the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManExtract( Ntl_Man_t * p ) -{ - // start the AIG manager - assert( p->pAig == NULL ); - p->pAig = Aig_ManStart( 10000 ); - // check the DFS traversal - if ( !Ntl_ManDfs( p ) ) - return 0; - // cleanup the AIG - Aig_ManCleanup( p->pAig ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Inserts the given mapping into the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping ) -{ - char Buffer[100]; - Vec_Ptr_t * vCopies; - Vec_Int_t * vCover; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pNode; - Ntl_Net_t * pNet, * pNetCo; - Ntl_Lut_t * pLut; - int i, k, nDigits; - // remove old nodes - pRoot = Vec_PtrEntry( p->vModels, 0 ); - Ntl_ModelForEachNode( pRoot, pNode, i ) - Vec_PtrWriteEntry( pRoot->vObjs, pNode->Id, NULL ); - // start mapping of AIG nodes into their copies - vCopies = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); - Ntl_ManForEachCiNet( p, pNet, i ) - Vec_PtrWriteEntry( vCopies, pNet->pFunc->Id, pNet ); - // create a new node for each LUT - vCover = Vec_IntAlloc( 1 << 16 ); - nDigits = Aig_Base10Log( Vec_PtrSize(vMapping) ); - Vec_PtrForEachEntry( vMapping, pLut, i ) - { - pNode = Ntl_ModelCreateNode( pRoot, pLut->nFanins ); - pNode->pSop = Ntl_SopFromTruth( p, pLut->pTruth, pLut->nFanins, vCover ); - if ( !Kit_TruthIsConst0(pLut->pTruth, pLut->nFanins) && !Kit_TruthIsConst1(pLut->pTruth, pLut->nFanins) ) - { - for ( k = 0; k < pLut->nFanins; k++ ) - { - pNet = Vec_PtrEntry( vCopies, pLut->pFanins[k] ); - if ( pNet == NULL ) - { - printf( "Ntl_ManInsert(): Internal error: Net not found.\n" ); - return 0; - } - Ntl_ObjSetFanin( pNode, pNet, k ); - } - } - sprintf( Buffer, "lut%0*d", nDigits, i ); - if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) ) - { - printf( "Ntl_ManInsert(): Internal error: Intermediate net name is not unique.\n" ); - return 0; - } - pNet = Ntl_ModelFindOrCreateNet( pRoot, Buffer ); - if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) - { - printf( "Ntl_ManInsert(): Internal error: Net has more than one fanin.\n" ); - return 0; - } - Vec_PtrWriteEntry( vCopies, pLut->Id, pNet ); - } - Vec_IntFree( vCover ); - // mark CIs and outputs of the registers - Ntl_ManForEachCiNet( p, pNetCo, i ) - pNetCo->nVisits = 101; - // update the CO pointers - Ntl_ManForEachCoNet( p, pNetCo, i ) - { - if ( pNetCo->nVisits == 101 ) - continue; - pNetCo->nVisits = 101; - pNet = Vec_PtrEntry( vCopies, Aig_Regular(pNetCo->pFunc)->Id ); - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = Aig_IsComplement(pNetCo->pFunc)? Ntl_ManStoreSop( p, "0 1\n" ) : Ntl_ManStoreSop( p, "1 1\n" ); - Ntl_ObjSetFanin( pNode, pNet, 0 ); - // update the CO driver net - pNetCo->pDriver = NULL; - if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) ) - { - printf( "Ntl_ManInsert(): Internal error: PO net has more than one fanin.\n" ); - return 0; - } - } - Vec_PtrFree( vCopies ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Extracts AIG from the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManPerformSynthesis( Ntl_Man_t * p ) -{ - extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ); - extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); - Aig_Man_t * pTemp; - Ntl_Net_t * pNet; - int i; - // perform synthesis -printf( "Pre-synthesis AIG: " ); -Aig_ManPrintStats( p->pAig ); -// p->pAig = Dar_ManBalance( pTemp = p->pAig, 1 ); - p->pAig = Dar_ManCompress( pTemp = p->pAig, 1, 1, 0 ); - Ntl_ManForEachCiNet( p, pNet, i ) - pNet->pFunc = Aig_ManPi( p->pAig, i ); - Ntl_ManForEachCoNet( p, pNet, i ) - pNet->pFunc = Aig_ObjChild0( Aig_ManPo( p->pAig, i ) ); - Aig_ManStop( pTemp ); -printf( "Post-synthesis AIG: " ); -Aig_ManPrintStats( p->pAig ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Testing procedure for insertion of mapping into the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManInsertTest( Ntl_Man_t * p ) -{ - Vec_Ptr_t * vMapping; - int RetValue; - if ( !Ntl_ManExtract( p ) ) - return 0; - assert( p->pAig != NULL ); - Ntl_ManPerformSynthesis( p ); - vMapping = Ntl_MappingFromAig( p->pAig ); - RetValue = Ntl_ManInsert( p, vMapping ); - Vec_PtrFree( vMapping ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Testing procedure for insertion of mapping into the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManInsertTestIf( Ntl_Man_t * p ) -{ - Vec_Ptr_t * vMapping; - int RetValue; - if ( !Ntl_ManExtract( p ) ) - return 0; - assert( p->pAig != NULL ); -// Ntl_ManPerformSynthesis( p ); - vMapping = Ntl_MappingIf( p, p->pAig ); - RetValue = Ntl_ManInsert( p, vMapping ); - Vec_PtrFree( vMapping ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlCheck.c b/src/aig/ntl/ntlCheck.c deleted file mode 100644 index d01c7d5e..00000000 --- a/src/aig/ntl/ntlCheck.c +++ /dev/null @@ -1,126 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Checks consistency of the netlist.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCheck( Ntl_Man_t * pMan ) -{ - // check that the models have unique names - // check that the models (except the first one) do not have boxes - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCheck( Ntl_Mod_t * pModel ) -{ - return 1; -} - - -/**Function************************************************************* - - Synopsis [Reads the verilog file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelFixNonDrivenNets( Ntl_Mod_t * pModel ) -{ - Vec_Ptr_t * vNets; - Ntl_Net_t * pNet; - Ntl_Obj_t * pNode; - int i; - - if ( Ntl_ModelIsBlackBox(pModel) ) - return; - - // check for non-driven nets - vNets = Vec_PtrAlloc( 100 ); - Ntl_ModelForEachNet( pModel, pNet, i ) - { - if ( pNet->pDriver != NULL ) - continue; - // add the constant 0 driver - pNode = Ntl_ModelCreateNode( pModel, 0 ); - pNode->pSop = Ntl_ManStoreSop( pModel->pMan, " 0\n" ); - Ntl_ModelSetNetDriver( pNode, pNet ); - // add the net to those for which the warning will be printed - Vec_PtrPush( vNets, pNet ); - } - - // print the warning - if ( Vec_PtrSize(vNets) > 0 ) - { - printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pModel->pName ); - Vec_PtrForEachEntry( vNets, pNet, i ) - { - printf( "%s%s", (i? ", ": ""), pNet->pName ); - if ( i == 3 ) - { - if ( Vec_PtrSize(vNets) > 3 ) - printf( " ..." ); - break; - } - } - printf( "\n" ); - } - Vec_PtrFree( vNets ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlDfs.c b/src/aig/ntl/ntlDfs.c deleted file mode 100644 index 1e9503a4..00000000 --- a/src/aig/ntl/ntlDfs.c +++ /dev/null @@ -1,184 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [DFS traversal.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Collects the nodes in a topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManDfs_rec( Ntl_Man_t * p, Ntl_Net_t * pNet ) -{ - Ntl_Obj_t * pObj; - Ntl_Net_t * pNetFanin; - int i; - // skip visited - if ( pNet->nVisits == 2 ) - return 1; - // if the node is on the path, this is a combinational loop - if ( pNet->nVisits == 1 ) - return 0; - // mark the node as the one on the path - pNet->nVisits = 1; - // derive the box - pObj = pNet->pDriver; - assert( Ntl_ObjIsNode(pObj) || Ntl_ObjIsBox(pObj) ); - // visit the input nets of the box - Ntl_ObjForEachFanin( pObj, pNetFanin, i ) - if ( !Ntl_ManDfs_rec( p, pNetFanin ) ) - return 0; - // add box inputs/outputs to COs/CIs - if ( Ntl_ObjIsBox(pObj) ) - { - int LevelCur, LevelMax = -AIG_INFINITY; - Vec_IntPush( p->vBox1Cos, Aig_ManPoNum(p->pAig) ); - Ntl_ObjForEachFanin( pObj, pNetFanin, i ) - { - LevelCur = Aig_ObjLevel( Aig_Regular(pNetFanin->pFunc) ); - LevelMax = AIG_MAX( LevelMax, LevelCur ); - Vec_PtrPush( p->vCos, pNetFanin ); - Aig_ObjCreatePo( p->pAig, pNetFanin->pFunc ); - } - Ntl_ObjForEachFanout( pObj, pNetFanin, i ) - { - Vec_PtrPush( p->vCis, pNetFanin ); - pNetFanin->pFunc = Aig_ObjCreatePi( p->pAig ); - Aig_ObjSetLevel( pNetFanin->pFunc, LevelMax + 1 ); - } -//printf( "Creating fake PO with ID = %d.\n", Aig_ManPo(p->pAig, Vec_IntEntryLast(p->vBox1Cos))->Id ); - } - // store the node - Vec_PtrPush( p->vNodes, pObj ); - if ( Ntl_ObjIsNode(pObj) ) - pNet->pFunc = Ntl_ManExtractAigNode( pObj ); - pNet->nVisits = 2; - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs DFS.] - - Description [Checks for combinational loops. Collects PI/PO nets. - Collects nodes in the topological order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManDfs( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - int i, nUselessObjects; - assert( Vec_PtrSize(p->vCis) == 0 ); - assert( Vec_PtrSize(p->vCos) == 0 ); - assert( Vec_PtrSize(p->vNodes) == 0 ); - assert( Vec_IntSize(p->vBox1Cos) == 0 ); - // get the root model - pRoot = Vec_PtrEntry( p->vModels, 0 ); - // collect primary inputs - Ntl_ModelForEachPi( pRoot, pObj, i ) - { - assert( Ntl_ObjFanoutNum(pObj) == 1 ); - pNet = Ntl_ObjFanout0(pObj); - Vec_PtrPush( p->vCis, pNet ); - pNet->pFunc = Aig_ObjCreatePi( p->pAig ); - if ( pNet->nVisits ) - { - printf( "Ntl_ManDfs(): Primary input appears twice in the list.\n" ); - return 0; - } - pNet->nVisits = 2; - } - // collect latch outputs - Ntl_ModelForEachLatch( pRoot, pObj, i ) - { - assert( Ntl_ObjFanoutNum(pObj) == 1 ); - pNet = Ntl_ObjFanout0(pObj); - Vec_PtrPush( p->vCis, pNet ); - pNet->pFunc = Aig_ObjCreatePi( p->pAig ); - if ( pNet->nVisits ) - { - printf( "Ntl_ManDfs(): Latch output is duplicated or defined as a primary input.\n" ); - return 0; - } - pNet->nVisits = 2; - } - // visit the nodes starting from primary outputs - Ntl_ModelForEachPo( pRoot, pObj, i ) - { - pNet = Ntl_ObjFanin0(pObj); - if ( !Ntl_ManDfs_rec( p, pNet ) ) - { - printf( "Ntl_ManDfs(): Error: Combinational loop is detected.\n" ); - Vec_PtrClear( p->vCis ); - Vec_PtrClear( p->vCos ); - Vec_PtrClear( p->vNodes ); - return 0; - } - Vec_PtrPush( p->vCos, pNet ); - Aig_ObjCreatePo( p->pAig, pNet->pFunc ); - } - // visit the nodes starting from latch inputs outputs - Ntl_ModelForEachLatch( pRoot, pObj, i ) - { - pNet = Ntl_ObjFanin0(pObj); - if ( !Ntl_ManDfs_rec( p, pNet ) ) - { - printf( "Ntl_ManDfs(): Error: Combinational loop is detected.\n" ); - Vec_PtrClear( p->vCis ); - Vec_PtrClear( p->vCos ); - Vec_PtrClear( p->vNodes ); - return 0; - } - Vec_PtrPush( p->vCos, pNet ); - Aig_ObjCreatePo( p->pAig, pNet->pFunc ); - } - // report the number of dangling objects - nUselessObjects = Ntl_ModelNodeNum(pRoot) + Ntl_ModelBoxNum(pRoot) - Vec_PtrSize(p->vNodes); - if ( nUselessObjects ) - printf( "The number of nodes that do not feed into POs = %d.\n", nUselessObjects ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlMan.c b/src/aig/ntl/ntlMan.c deleted file mode 100644 index 9b4aff5f..00000000 --- a/src/aig/ntl/ntlMan.c +++ /dev/null @@ -1,196 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Netlist manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the netlist manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManAlloc( char * pFileName ) -{ - Ntl_Man_t * p; - // start the manager - p = ALLOC( Ntl_Man_t, 1 ); - memset( p, 0, sizeof(Ntl_Man_t) ); - p->vModels = Vec_PtrAlloc( 1000 ); - p->vCis = Vec_PtrAlloc( 1000 ); - p->vCos = Vec_PtrAlloc( 1000 ); - p->vNodes = Vec_PtrAlloc( 1000 ); - p->vBox1Cos = Vec_IntAlloc( 1000 ); - // start the manager - p->pMemObjs = Aig_MmFlexStart(); - p->pMemSops = Aig_MmFlexStart(); - // same the names - p->pName = Ntl_ManStoreFileName( p, pFileName ); - p->pSpec = Ntl_ManStoreName( p, pFileName ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the netlist manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManFree( Ntl_Man_t * p ) -{ - if ( p->vModels ) - { - Ntl_Mod_t * pModel; - int i; - Ntl_ManForEachModel( p, pModel, i ) - Ntl_ModelFree( pModel ); - Vec_PtrFree( p->vModels ); - } - if ( p->vCis ) Vec_PtrFree( p->vCis ); - if ( p->vCos ) Vec_PtrFree( p->vCos ); - if ( p->vNodes ) Vec_PtrFree( p->vNodes ); - if ( p->vBox1Cos ) Vec_IntFree( p->vBox1Cos ); - if ( p->pMemObjs ) Aig_MmFlexStop( p->pMemObjs, 0 ); - if ( p->pMemSops ) Aig_MmFlexStop( p->pMemSops, 0 ); - if ( p->pAig ) Aig_ManStop( p->pAig ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Find the model with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, char * pName ) -{ - Ntl_Mod_t * pModel; - int i; - Vec_PtrForEachEntry( p->vModels, pModel, i ) - if ( !strcmp( pModel->pName, pName ) ) - return pModel; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Deallocates the netlist manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManPrintStats( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - pRoot = Vec_PtrEntry( p->vModels, 0 ); - printf( "%-15s : ", p->pName ); - printf( "pi = %5d ", Ntl_ModelPiNum(pRoot) ); - printf( "po = %5d ", Ntl_ModelPoNum(pRoot) ); - printf( "latch = %5d ", Ntl_ModelLatchNum(pRoot) ); - printf( "node = %5d ", Ntl_ModelNodeNum(pRoot) ); - printf( "box = %4d ", Ntl_ModelBoxNum(pRoot) ); - printf( "model = %3d", Vec_PtrSize(p->vModels) ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Allocates the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName ) -{ - Ntl_Mod_t * p; - // start the manager - p = ALLOC( Ntl_Mod_t, 1 ); - memset( p, 0, sizeof(Ntl_Mod_t) ); - p->pMan = pMan; - p->pName = Ntl_ManStoreName( p->pMan, pName ); - Vec_PtrPush( pMan->vModels, p ); - p->vObjs = Vec_PtrAlloc( 10000 ); - p->vPis = Vec_PtrAlloc( 1000 ); - p->vPos = Vec_PtrAlloc( 1000 ); - // start the table - p->nTableSize = Aig_PrimeCudd( 10000 ); - p->pTable = ALLOC( Ntl_Net_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Ntl_Net_t *) * p->nTableSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelFree( Ntl_Mod_t * p ) -{ - if ( p->vRequireds ) Vec_IntFree( p->vRequireds ); - if ( p->vArrivals ) Vec_IntFree( p->vArrivals ); - if ( p->vDelays ) Vec_IntFree( p->vDelays ); - Vec_PtrFree( p->vObjs ); - Vec_PtrFree( p->vPis ); - Vec_PtrFree( p->vPos ); - free( p->pTable ); - free( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlMap.c b/src/aig/ntl/ntlMap.c deleted file mode 100644 index 59c40453..00000000 --- a/src/aig/ntl/ntlMap.c +++ /dev/null @@ -1,624 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlMap.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Derives mapped network from AIG.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates mapping for the given AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntl_MappingAlloc( int nLuts, int nVars ) -{ - char * pMemory; - Ntl_Lut_t ** pArray; - int nEntrySize, i; - nEntrySize = sizeof(Ntl_Lut_t) + sizeof(int) * nVars + sizeof(unsigned) * Aig_TruthWordNum(nVars); - pArray = (Ntl_Lut_t **)malloc( (sizeof(Ntl_Lut_t *) + nEntrySize) * nLuts ); - pMemory = (char *)(pArray + nLuts); - memset( pMemory, 0, nEntrySize * nLuts ); - for ( i = 0; i < nLuts; i++ ) - { - pArray[i] = (Ntl_Lut_t *)pMemory; - pArray[i]->pFanins = (int *)(pMemory + sizeof(Ntl_Lut_t)); - pArray[i]->pTruth = (unsigned *)(pMemory + sizeof(Ntl_Lut_t) + sizeof(int) * nVars); - pMemory += nEntrySize; - } - return Vec_PtrAllocArray( (void **)pArray, nLuts ); -} - -/**Function************************************************************* - - Synopsis [Derives trivial mapping from the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntl_MappingFromAig( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMapping; - Ntl_Lut_t * pLut; - Aig_Obj_t * pObj; - int i, k = 0, nBytes = 4; - vMapping = Ntl_MappingAlloc( Aig_ManAndNum(p) + (int)(Aig_ManConst1(p)->nRefs > 0), 2 ); - if ( Aig_ManConst1(p)->nRefs > 0 ) - { - pLut = Vec_PtrEntry( vMapping, k++ ); - pLut->Id = 0; - pLut->nFanins = 0; - memset( pLut->pTruth, 0xFF, nBytes ); - } - Aig_ManForEachNode( p, pObj, i ) - { - pLut = Vec_PtrEntry( vMapping, k++ ); - pLut->Id = pObj->Id; - pLut->nFanins = 2; - pLut->pFanins[0] = Aig_ObjFaninId0(pObj); - pLut->pFanins[1] = Aig_ObjFaninId1(pObj); - if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) - memset( pLut->pTruth, 0x11, nBytes ); - else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) - memset( pLut->pTruth, 0x22, nBytes ); - else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) - memset( pLut->pTruth, 0x44, nBytes ); - else if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) - memset( pLut->pTruth, 0x88, nBytes ); - } - assert( k == Vec_PtrSize(vMapping) ); - return vMapping; -} - - -#include "fpgaInt.h" - -/**Function************************************************************* - - Synopsis [Recursively derives the truth table for the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ntl_FpgaComputeTruth_rec( Fpga_Cut_t * pCut, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore, Vec_Ptr_t * vVisited, int nVars, int * pnCounter ) -{ - unsigned * pTruth, * pTruth0, * pTruth1; - assert( !Fpga_IsComplement(pCut) ); - // if the cut is visited, return the result - if ( pCut->pRoot ) - return (unsigned *)pCut->pRoot; - // compute the functions of the children - pTruth0 = Ntl_FpgaComputeTruth_rec( Fpga_CutRegular(pCut->pOne), vTruthElem, vTruthStore, vVisited, nVars, pnCounter ); - if ( Fpga_CutIsComplement(pCut->pOne) ) - Kit_TruthNot( pTruth0, pTruth0, nVars ); - pTruth1 = Ntl_FpgaComputeTruth_rec( Fpga_CutRegular(pCut->pTwo), vTruthElem, vTruthStore, vVisited, nVars, pnCounter ); - if ( Fpga_CutIsComplement(pCut->pTwo) ) - Kit_TruthNot( pTruth1, pTruth1, nVars ); - // get the function of the cut - pTruth = Vec_PtrEntry( vTruthStore, (*pnCounter)++ ); - Kit_TruthAnd( pTruth, pTruth0, pTruth1, nVars ); - if ( pCut->Phase ) - Kit_TruthNot( pTruth, pTruth, nVars ); - assert( pCut->pRoot == NULL ); - pCut->pRoot = (Fpga_Node_t *)pTruth; - // add this cut to the visited list - Vec_PtrPush( vVisited, pCut ); - return pTruth; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table for one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ntl_FpgaComputeTruth( Fpga_Cut_t * pCut, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore, Vec_Ptr_t * vVisited, int nVars ) -{ - unsigned * pTruth; - int i, nCounter = 0; - assert( pCut->nLeaves > 1 ); - // set the leaf variables - for ( i = 0; i < pCut->nLeaves; i++ ) - pCut->ppLeaves[i]->pCuts->pRoot = (Fpga_Node_t *)Vec_PtrEntry( vTruthElem, i ); - // recursively compute the function - Vec_PtrClear( vVisited ); - pTruth = Ntl_FpgaComputeTruth_rec( pCut, vTruthElem, vTruthStore, vVisited, nVars, &nCounter ); - // clean the intermediate BDDs - for ( i = 0; i < pCut->nLeaves; i++ ) - pCut->ppLeaves[i]->pCuts->pRoot = NULL; - Vec_PtrForEachEntry( vVisited, pCut, i ) - pCut->pRoot = NULL; - return pTruth; -} - - -/**Function************************************************************* - - Synopsis [Load the network into FPGA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Man_t * Ntl_ManToFpga( Aig_Man_t * p ) -{ - Fpga_Man_t * pMan; - Aig_Obj_t * pNode;//, * pFanin, * pPrev; - float * pfArrivals; - int i; - // start the mapping manager and set its parameters - pMan = Fpga_ManCreate( Aig_ManPiNum(p), Aig_ManPoNum(p), 0 ); - if ( pMan == NULL ) - return NULL; - // set the arrival times - pfArrivals = ALLOC( float, Aig_ManPiNum(p) ); - memset( pfArrivals, 0, sizeof(float) * Aig_ManPiNum(p) ); - Fpga_ManSetInputArrivals( pMan, pfArrivals ); - // create PIs and remember them in the old nodes - Aig_ManConst1(p)->pData = Fpga_ManReadConst1(pMan); - Aig_ManForEachPi( p, pNode, i ) - pNode->pData = Fpga_ManReadInputs(pMan)[i]; - // load the AIG into the mapper - Aig_ManForEachNode( p, pNode, i ) - { - pNode->pData = Fpga_NodeAnd( pMan, - Fpga_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), - Fpga_NotCond( Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) ); - // set up the choice node -// if ( Aig_AigNodeIsChoice( pNode ) ) -// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) -// { -// Fpga_NodeSetNextE( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); -// Fpga_NodeSetRepr( (If_Obj_t *)pFanin->pData, (If_Obj_t *)pNode->pData ); -// } - } - // set the primary outputs while copying the phase - Aig_ManForEachPo( p, pNode, i ) - Fpga_ManReadOutputs(pMan)[i] = Fpga_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ); - assert( Fpga_NodeVecReadSize(pMan->vAnds) == Aig_ManNodeNum(p) ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Creates the mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntl_ManFromFpga( Aig_Man_t * p, Fpga_Man_t * pMan ) -{ - Fpga_NodeVec_t * vFpgaMap; - Fpga_Node_t ** ppLeaves, * pNode; - Fpga_Cut_t * pCutBest; - Vec_Ptr_t * vTruthElem, * vTruthStore, * vVisited, * vMapping; - Vec_Int_t * vFpgaToAig; - Aig_Obj_t * pObj; - Ntl_Lut_t * pLut; - unsigned * pTruth; - int i, k, nLuts, nLeaves, nWords, nVarsMax; - // create mapping of FPGA nodes into AIG nodes - vFpgaToAig = Vec_IntStart( Aig_ManObjNumMax(p) ); - Vec_IntFill( vFpgaToAig, Aig_ManObjNumMax(p), -1 ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjIsPo(pObj) ) - continue; - if ( Aig_ObjIsConst1(pObj) && pObj->pData == NULL ) - continue; - pNode = pObj->pData; - assert( pNode != NULL ); - Vec_IntWriteEntry( vFpgaToAig, Fpga_NodeReadNum(pNode), pObj->Id ); - } - // create the mapping - - - // make sure nodes are in the top order!!! - - - nVarsMax = Fpga_ManReadVarMax( pMan ); - nWords = Aig_TruthWordNum( nVarsMax ); - vFpgaMap = Fpga_ManReadMapping( pMan ); - vMapping = Ntl_MappingAlloc( vFpgaMap->nSize + (int)(Aig_ManConst1(p)->nRefs > 0), nVarsMax ); - nLuts = 0; - if ( Aig_ManConst1(p)->nRefs > 0 ) - { - pLut = Vec_PtrEntry( vMapping, nLuts++ ); - pLut->Id = 0; - pLut->nFanins = 0; - memset( pLut->pTruth, 0xFF, 4 * nWords ); - } - vVisited = Vec_PtrAlloc( 1000 ); - vTruthElem = Vec_PtrAllocTruthTables( nVarsMax ); - vTruthStore = Vec_PtrAllocSimInfo( 256, nWords ); - for ( i = 0; i < vFpgaMap->nSize; i++ ) - { - // get the best cut - pNode = vFpgaMap->pArray[i]; - pCutBest = Fpga_NodeReadCutBest( pNode ); - nLeaves = Fpga_CutReadLeavesNum( pCutBest ); - ppLeaves = Fpga_CutReadLeaves( pCutBest ); - // fill the LUT - pLut = Vec_PtrEntry( vMapping, nLuts++ ); - pLut->Id = Vec_IntEntry( vFpgaToAig, Fpga_NodeReadNum(pNode) ); - pLut->nFanins = nLeaves; - for ( k = 0; k < nLeaves; k++ ) - pLut->pFanins[k] = Vec_IntEntry( vFpgaToAig, Fpga_NodeReadNum(ppLeaves[k]) ); - // compute the truth table - pTruth = Ntl_FpgaComputeTruth( pCutBest, vTruthElem, vTruthStore, vVisited, nVarsMax ); - memcpy( pLut->pTruth, pTruth, 4 * nWords ); - } - assert( nLuts == Vec_PtrSize(vMapping) ); - Vec_IntFree( vFpgaToAig ); - Vec_PtrFree( vVisited ); - Vec_PtrFree( vTruthElem ); - Vec_PtrFree( vTruthStore ); - return vMapping; -} - -/**Function************************************************************* - - Synopsis [Interface with the FPGA mapping package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntl_MappingFpga( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMapping; - Fpga_Man_t * pMan; - // print a warning about choice nodes - if ( p->pEquivs ) - printf( "Ntl_MappingFpga(): Performing FPGA mapping with choices.\n" ); - // perform FPGA mapping - pMan = Ntl_ManToFpga( p ); - if ( pMan == NULL ) - return NULL; - if ( !Fpga_Mapping( pMan ) ) - { - Fpga_ManFree( pMan ); - return NULL; - } - // transform the result of mapping into a BDD network - vMapping = Ntl_ManFromFpga( p, pMan ); - Fpga_ManFree( pMan ); - if ( vMapping == NULL ) - return NULL; - return vMapping; -} - - - - -#include "if.h" - -/**Function************************************************************* - - Synopsis [Load the network into FPGA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntk_ManSetIfParsDefault( If_Par_t * pPars ) -{ -// extern void * Abc_FrameReadLibLut(); - // set defaults - memset( pPars, 0, sizeof(If_Par_t) ); - // user-controlable paramters -// pPars->nLutSize = -1; - pPars->nLutSize = 6; - pPars->nCutsMax = 8; - pPars->nFlowIters = 1; - pPars->nAreaIters = 2; - pPars->DelayTarget = -1; - pPars->fPreprocess = 1; - pPars->fArea = 0; - pPars->fFancy = 0; - pPars->fExpRed = 0; - pPars->fLatchPaths = 0; - pPars->fEdge = 1; - pPars->fCutMin = 1; - pPars->fSeqMap = 0; - pPars->fVerbose = 1; - // internal parameters - pPars->fTruth = 1; - pPars->nLatches = 0; - pPars->fLiftLeaves = 0; -// pPars->pLutLib = Abc_FrameReadLibLut(); - pPars->pLutLib = NULL; - pPars->pTimesArr = NULL; - pPars->pTimesArr = NULL; - pPars->pFuncCost = NULL; -/* - if ( pPars->nLutSize == -1 ) - { - if ( pPars->pLutLib == NULL ) - { - printf( "The LUT library is not given.\n" ); - return; - } - // get LUT size from the library - pPars->nLutSize = pPars->pLutLib->LutMax; - } -*/ -} - -/**Function************************************************************* - - Synopsis [Load the network into FPGA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Man_t * Ntk_ManToIf_old( Aig_Man_t * p, If_Par_t * pPars ) -{ - If_Man_t * pIfMan; - Aig_Obj_t * pNode;//, * pFanin, * pPrev; - Vec_Ptr_t * vNodes; - int i; - // start the mapping manager and set its parameters - pIfMan = If_ManStart( pPars ); - // print warning about excessive memory usage - if ( 1.0 * Aig_ManObjNum(p) * 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 * Aig_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Aig_ManObjNum(p) ); - // load the AIG into the mapper - vNodes = Aig_ManDfsPio( p ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Aig_ObjIsAnd(pNode) ) - pNode->pData = (Aig_Obj_t *)If_ManCreateAnd( pIfMan, - If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), - If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) ); - else if ( Aig_ObjIsPi(pNode) ) - pNode->pData = If_ManCreateCi( pIfMan ); - else if ( Aig_ObjIsPo(pNode) ) - If_ManCreateCo( pIfMan, If_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) ); - else if ( Aig_ObjIsConst1(pNode) ) - Aig_ManConst1(p)->pData = If_ManConst1( pIfMan ); - else // add the node to the mapper - assert( 0 ); - // set up the choice node -// if ( Aig_AigNodeIsChoice( pNode ) ) -// { -// pIfMan->nChoices++; -// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) -// If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); -// If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); -// } - } - Vec_PtrFree( vNodes ); - return pIfMan; -} - -/**Function************************************************************* - - Synopsis [Load the network into FPGA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Man_t * Ntk_ManToIf( Aig_Man_t * p, If_Par_t * pPars ) -{ - If_Man_t * pIfMan; - Aig_Obj_t * pNode;//, * pFanin, * pPrev; - int i; - // start the mapping manager and set its parameters - pIfMan = If_ManStart( pPars ); - // print warning about excessive memory usage - if ( 1.0 * Aig_ManObjNum(p) * 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 * Aig_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Aig_ManObjNum(p) ); - // load the AIG into the mapper - Aig_ManForEachObj( p, pNode, i ) - { - if ( Aig_ObjIsAnd(pNode) ) - pNode->pData = (Aig_Obj_t *)If_ManCreateAnd( pIfMan, - If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), - If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) ); - else if ( Aig_ObjIsPi(pNode) ) - { - pNode->pData = If_ManCreateCi( pIfMan ); - ((If_Obj_t *)pNode->pData)->Level = pNode->Level; - } - else if ( Aig_ObjIsPo(pNode) ) - If_ManCreateCo( pIfMan, If_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) ); - else if ( Aig_ObjIsConst1(pNode) ) - Aig_ManConst1(p)->pData = If_ManConst1( pIfMan ); - else // add the node to the mapper - assert( 0 ); - // set up the choice node -// if ( Aig_AigNodeIsChoice( pNode ) ) -// { -// pIfMan->nChoices++; -// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) -// If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); -// If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); -// } - } - return pIfMan; -} - -/**Function************************************************************* - - Synopsis [Creates the mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntk_ManFromIf( Aig_Man_t * p, If_Man_t * pMan ) -{ - Vec_Ptr_t * vIfMap; - If_Obj_t * pNode, * pLeaf; - If_Cut_t * pCutBest; - Vec_Ptr_t * vMapping; - Vec_Int_t * vIfToAig; - Aig_Obj_t * pObj; - Ntl_Lut_t * pLut; - int * ppLeaves; - int i, k, nLuts, nLeaves, nWords, nVarsMax; - // create mapping of If nodes into AIG nodes - vIfToAig = Vec_IntStart( Aig_ManObjNumMax(p) ); - Vec_IntFill( vIfToAig, Aig_ManObjNumMax(p), -1 ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjIsPo(pObj) ) - continue; - if ( Aig_ObjIsConst1(pObj) && pObj->pData == NULL ) - continue; - if ( Aig_ObjIsPi(pObj) && pObj->pData == NULL ) - continue; - pNode = pObj->pData; - assert( pNode != NULL ); - Vec_IntWriteEntry( vIfToAig, pNode->Id, pObj->Id ); - } - // create the mapping - vIfMap = If_ManCollectMappingDirect( pMan ); - nVarsMax = pMan->pPars->nLutSize; - nWords = Aig_TruthWordNum( nVarsMax ); - vMapping = Ntl_MappingAlloc( Vec_PtrSize(vIfMap) + (int)(Aig_ManConst1(p)->nRefs > 0), nVarsMax ); - nLuts = 0; - if ( Aig_ManConst1(p)->nRefs > 0 ) - { - pLut = Vec_PtrEntry( vMapping, nLuts++ ); - pLut->Id = 0; - pLut->nFanins = 0; - memset( pLut->pTruth, 0xFF, 4 * nWords ); - } - Vec_PtrForEachEntry( vIfMap, pNode, i ) - { - // get the best cut - pCutBest = If_ObjCutBest(pNode); - nLeaves = If_CutLeaveNum( pCutBest ); - ppLeaves = If_CutLeaves( pCutBest ); - // fill the LUT - pLut = Vec_PtrEntry( vMapping, nLuts++ ); - pLut->Id = Vec_IntEntry( vIfToAig, pNode->Id ); - pLut->nFanins = nLeaves; - If_CutForEachLeaf( pMan, pCutBest, pLeaf, k ) - pLut->pFanins[k] = Vec_IntEntry( vIfToAig, pLeaf->Id ); - // compute the truth table - memcpy( pLut->pTruth, If_CutTruth(pCutBest), 4 * nWords ); - } - assert( nLuts == Vec_PtrSize(vMapping) ); - Vec_IntFree( vIfToAig ); - Vec_PtrFree( vIfMap ); - return vMapping; -} - -/**Function************************************************************* - - Synopsis [Interface with the FPGA mapping package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntl_MappingIf( Ntl_Man_t * pMan, Aig_Man_t * p ) -{ - Vec_Ptr_t * vMapping; - If_Par_t Pars, * pPars = &Pars; - If_Man_t * pIfMan; - // perform FPGA mapping - Ntk_ManSetIfParsDefault( pPars ); - // set the arrival times - pPars->pTimesArr = ALLOC( float, Aig_ManPiNum(p) ); - memset( pPars->pTimesArr, 0, sizeof(float) * Aig_ManPiNum(p) ); - // translate into the mapper - pIfMan = Ntk_ManToIf( p, pPars ); - if ( pIfMan == NULL ) - return NULL; - pIfMan->pManTim = Ntl_ManCreateTiming( pMan ); - if ( !If_ManPerformMapping( pIfMan ) ) - { - If_ManStop( pIfMan ); - return NULL; - } - // transform the result of mapping into the new network - vMapping = Ntk_ManFromIf( p, pIfMan ); - If_ManStop( pIfMan ); - if ( vMapping == NULL ) - return NULL; - return vMapping; -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlObj.c b/src/aig/ntl/ntlObj.c deleted file mode 100644 index 2e39fbbf..00000000 --- a/src/aig/ntl/ntlObj.c +++ /dev/null @@ -1,238 +0,0 @@ -/**CFile**************************************************************** - - FileName [.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - 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 "ntl.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the primary input.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Obj_t * Ntl_ModelCreatePi( Ntl_Mod_t * pModel ) -{ - Ntl_Obj_t * p; - p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) ); - memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) ); - p->Id = Vec_PtrSize( pModel->vObjs ); - Vec_PtrPush( pModel->vObjs, p ); - Vec_PtrPush( pModel->vPis, p ); - p->pModel = pModel; - p->Type = NTL_OBJ_PI; - p->nFanins = 0; - p->nFanouts = 1; - pModel->nObjs[NTL_OBJ_PI]++; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the primary output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Obj_t * Ntl_ModelCreatePo( Ntl_Mod_t * pModel, Ntl_Net_t * pNet ) -{ - Ntl_Obj_t * p; - p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) ); - memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) ); - p->Id = Vec_PtrSize( pModel->vObjs ); - Vec_PtrPush( pModel->vObjs, p ); - Vec_PtrPush( pModel->vPos, p ); - p->pModel = pModel; - p->Type = NTL_OBJ_PO; - p->nFanins = 1; - p->nFanouts = 0; - p->pFanio[0] = pNet; - pModel->nObjs[NTL_OBJ_PO]++; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the primary output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Obj_t * Ntl_ModelCreateLatch( Ntl_Mod_t * pModel ) -{ - Ntl_Obj_t * p; - p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * 3 ); - memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * 3 ); - p->Id = Vec_PtrSize( pModel->vObjs ); - Vec_PtrPush( pModel->vObjs, p ); - p->pModel = pModel; - p->Type = NTL_OBJ_LATCH; - p->nFanins = 2; - p->nFanouts = 1; - pModel->nObjs[NTL_OBJ_LATCH]++; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Obj_t * Ntl_ModelCreateNode( Ntl_Mod_t * pModel, int nFanins ) -{ - Ntl_Obj_t * p; - p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + 1) ); - memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + 1) ); - p->Id = Vec_PtrSize( pModel->vObjs ); - Vec_PtrPush( pModel->vObjs, p ); - p->pModel = pModel; - p->Type = NTL_OBJ_NODE; - p->nFanins = nFanins; - p->nFanouts = 1; - pModel->nObjs[NTL_OBJ_NODE]++; - return p; -} - -/**Function************************************************************* - - Synopsis [Create the latch.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Obj_t * Ntl_ModelCreateBox( Ntl_Mod_t * pModel, int nFanins, int nFanouts ) -{ - Ntl_Obj_t * p; - p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + nFanouts) ); - memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + nFanouts) ); - p->Id = Vec_PtrSize( pModel->vObjs ); - Vec_PtrPush( pModel->vObjs, p ); - p->pModel = pModel; - p->Type = NTL_OBJ_BOX; - p->nFanins = nFanins; - p->nFanouts = nFanouts; - pModel->nObjs[NTL_OBJ_BOX]++; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates memory and copies the name into it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ntl_ManStoreName( Ntl_Man_t * p, char * pName ) -{ - char * pStore; - pStore = Aig_MmFlexEntryFetch( p->pMemObjs, strlen(pName) + 1 ); - strcpy( pStore, pName ); - return pStore; -} - -/**Function************************************************************* - - Synopsis [Allocates memory and copies the SOP into it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ntl_ManStoreSop( Ntl_Man_t * p, char * pSop ) -{ - char * pStore; - pStore = Aig_MmFlexEntryFetch( p->pMemSops, strlen(pSop) + 1 ); - strcpy( pStore, pSop ); - return pStore; -} - -/**Function************************************************************* - - Synopsis [Allocates memory and copies the root of file name there.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ntl_ManStoreFileName( Ntl_Man_t * p, char * pFileName ) -{ - char * pBeg, * pEnd, * pStore, * pCur; - // find the first dot - for ( pEnd = pFileName; *pEnd; pEnd++ ) - if ( *pEnd == '.' ) - break; - // find the first char - for ( pBeg = pEnd - 1; pBeg >= pFileName; pBeg-- ) - if ( !((*pBeg >= 'a' && *pBeg <= 'z') || (*pBeg >= 'A' && *pBeg <= 'Z') || (*pBeg >= '0' && *pBeg <= '9') || *pBeg == '_') ) - break; - pBeg++; - // fill up storage - pStore = Aig_MmFlexEntryFetch( p->pMemSops, pEnd - pBeg + 1 ); - for ( pCur = pStore; pBeg < pEnd; pBeg++, pCur++ ) - *pCur = *pBeg; - *pCur = 0; - return pStore; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlReadBlif.c b/src/aig/ntl/ntlReadBlif.c deleted file mode 100644 index d085b5e6..00000000 --- a/src/aig/ntl/ntlReadBlif.c +++ /dev/null @@ -1,1163 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlReadBlif.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read BLIF file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 8, 2007.] - - Revision [$Id: ntlReadBlif.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ioa_ReadMod_t_ Ioa_ReadMod_t; // parsing model -typedef struct Ioa_ReadMan_t_ Ioa_ReadMan_t; // parsing manager - -struct Ioa_ReadMod_t_ -{ - // file lines - char * pFirst; // .model line - Vec_Ptr_t * vInputs; // .inputs lines - Vec_Ptr_t * vOutputs; // .outputs lines - Vec_Ptr_t * vLatches; // .latch lines - Vec_Ptr_t * vNames; // .names lines - Vec_Ptr_t * vSubckts; // .subckt lines - Vec_Ptr_t * vDelays; // .delay lines - Vec_Ptr_t * vArrivals; // .input_arrival lines - Vec_Ptr_t * vRequireds; // .output_required lines - int fBlackBox; // indicates blackbox model - // the resulting network - Ntl_Mod_t * pNtk; - // the parent manager - Ioa_ReadMan_t * pMan; -}; - -struct Ioa_ReadMan_t_ -{ - // general info about file - 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 - Ntl_Man_t * pDesign; // the design under construction - // intermediate storage for models - Vec_Ptr_t * vModels; // vector of models - Ioa_ReadMod_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 Ioa_ReadMan_t * Ioa_ReadAlloc(); -static void Ioa_ReadFree( Ioa_ReadMan_t * p ); -static Ioa_ReadMod_t * Ioa_ReadModAlloc(); -static void Ioa_ReadModFree( Ioa_ReadMod_t * p ); -static char * Ioa_ReadLoadFile( char * pFileName ); -static void Ioa_ReadReadPreparse( Ioa_ReadMan_t * p ); -static int Ioa_ReadReadInterfaces( Ioa_ReadMan_t * p ); -static Ntl_Man_t * Ioa_ReadParse( Ioa_ReadMan_t * p ); -static int Ioa_ReadParseLineModel( Ioa_ReadMod_t * p, char * pLine ); -static int Ioa_ReadParseLineInputs( Ioa_ReadMod_t * p, char * pLine ); -static int Ioa_ReadParseLineOutputs( Ioa_ReadMod_t * p, char * pLine ); -static int Ioa_ReadParseLineLatch( Ioa_ReadMod_t * p, char * pLine ); -static int Ioa_ReadParseLineSubckt( Ioa_ReadMod_t * p, char * pLine ); -static int Ioa_ReadParseLineDelay( Ioa_ReadMod_t * p, char * pLine ); -static int Ioa_ReadParseLineTimes( Ioa_ReadMod_t * p, char * pLine, int fOutput ); -static int Ioa_ReadParseLineNamesBlif( Ioa_ReadMod_t * p, char * pLine ); - -static int Ioa_ReadCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } -static int Ioa_ReadCharIsSopSymb( char s ) { return s == '0' || s == '1' || s == '-' || s == '\r' || s == '\n'; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the network from the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck ) -{ - FILE * pFile; - Ioa_ReadMan_t * p; - Ntl_Mod_t * pNtk; - Ntl_Man_t * pDesign; - int i; - - // check that the file is available - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Ioa_ReadBlif(): The file is unavailable (absent or open).\n" ); - return 0; - } - fclose( pFile ); - - // start the file reader - p = Ioa_ReadAlloc(); - p->pFileName = pFileName; - p->pBuffer = Ioa_ReadLoadFile( pFileName ); - if ( p->pBuffer == NULL ) - { - Ioa_ReadFree( p ); - return NULL; - } - // set the design name - p->pDesign = Ntl_ManAlloc( pFileName ); - // prepare the file for parsing - Ioa_ReadReadPreparse( p ); - // parse interfaces of each network - if ( !Ioa_ReadReadInterfaces( p ) ) - { - if ( p->sError[0] ) - fprintf( stdout, "%s\n", p->sError ); - Ioa_ReadFree( p ); - return NULL; - } - // construct the network - pDesign = Ioa_ReadParse( p ); - if ( p->sError[0] ) - fprintf( stdout, "%s\n", p->sError ); - if ( pDesign == NULL ) - { - Ioa_ReadFree( p ); - return NULL; - } - p->pDesign = NULL; - Ioa_ReadFree( p ); -// pDesign should be linked to all models of the design - - // make sure that everything is okay with the network structure - if ( fCheck ) - { - // check individual models - Vec_PtrForEachEntry( pDesign->vModels, pNtk, i ) - { - if ( !Ntl_ModelCheck( pNtk ) ) - { - printf( "Ioa_ReadBlif: The network check has failed for network %s.\n", pNtk->pName ); - Ntl_ManFree( pDesign ); - return NULL; - } - } - // check the hierarchy - if ( !Ntl_ManCheck( pDesign ) ) - { - printf( "Ioa_ReadBlif: The hierarchy check has failed for design %s.\n", pDesign->pName ); - Ntl_ManFree( pDesign ); - return NULL; - } - - } -//Ioa_WriteBlif( pDesign, "_temp_.blif" ); - return pDesign; -} - -/**Function************************************************************* - - Synopsis [Allocates the BLIF parsing structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Ioa_ReadMan_t * Ioa_ReadAlloc() -{ - Ioa_ReadMan_t * p; - p = ALLOC( Ioa_ReadMan_t, 1 ); - memset( p, 0, sizeof(Ioa_ReadMan_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 Ioa_ReadFree( Ioa_ReadMan_t * p ) -{ - Ioa_ReadMod_t * pMod; - int i; - if ( p->pDesign ) - Ntl_ManFree( p->pDesign ); - if ( p->pBuffer ) - free( p->pBuffer ); - if ( p->vLines ) - Vec_PtrFree( p->vLines ); - if ( p->vModels ) - { - Vec_PtrForEachEntry( p->vModels, pMod, i ) - Ioa_ReadModFree( 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 Ioa_ReadMod_t * Ioa_ReadModAlloc() -{ - Ioa_ReadMod_t * p; - p = ALLOC( Ioa_ReadMod_t, 1 ); - memset( p, 0, sizeof(Ioa_ReadMod_t) ); - p->vInputs = Vec_PtrAlloc( 512 ); - p->vOutputs = Vec_PtrAlloc( 512 ); - p->vLatches = Vec_PtrAlloc( 512 ); - p->vNames = Vec_PtrAlloc( 512 ); - p->vSubckts = Vec_PtrAlloc( 512 ); - p->vDelays = Vec_PtrAlloc( 512 ); - p->vArrivals = Vec_PtrAlloc( 512 ); - p->vRequireds = Vec_PtrAlloc( 512 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the BLIF parsing structure for one model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ioa_ReadModFree( Ioa_ReadMod_t * p ) -{ - Vec_PtrFree( p->vInputs ); - Vec_PtrFree( p->vOutputs ); - Vec_PtrFree( p->vLatches ); - Vec_PtrFree( p->vNames ); - Vec_PtrFree( p->vSubckts ); - Vec_PtrFree( p->vDelays ); - Vec_PtrFree( p->vArrivals ); - Vec_PtrFree( p->vRequireds ); - free( p ); -} - - - -/**Function************************************************************* - - Synopsis [Counts the number of given chars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadCountChars( char * pLine, char Char ) -{ - char * pCur; - int Counter = 0; - for ( pCur = pLine; *pCur; pCur++ ) - if ( *pCur == Char ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Collects the already split tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ioa_ReadCollectTokens( 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 Ioa_ReadSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) -{ - char * pCur; - // clear spaces - for ( pCur = pLine; *pCur != Stop; pCur++ ) - if ( Ioa_ReadCharIsSpace(*pCur) ) - *pCur = 0; - // collect tokens - Ioa_ReadCollectTokens( vTokens, pLine, pCur ); -} - -/**Function************************************************************* - - Synopsis [Splits the line into tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ioa_ReadSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char ) -{ - char * pCur; - // clear spaces - for ( pCur = pLine; *pCur != Stop; pCur++ ) - if ( Ioa_ReadCharIsSpace(*pCur) || *pCur == Char ) - *pCur = 0; - // collect tokens - Ioa_ReadCollectTokens( vTokens, pLine, pCur ); -} - -/**Function************************************************************* - - Synopsis [Returns the 1-based number of the line in which the token occurs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadGetLine( Ioa_ReadMan_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 * Ioa_ReadLoadFile( char * pFileName ) -{ - FILE * pFile; - int nFileSize; - char * pContents; - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Ioa_ReadLoadFile(): The file is unavailable (absent or open).\n" ); - return NULL; - } - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - if ( nFileSize == 0 ) - { - printf( "Ioa_ReadLoadFile(): 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 Ioa_ReadReadPreparse( Ioa_ReadMan_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 ( !Ioa_ReadCharIsSpace(*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 ( Ioa_ReadCharIsSpace(*pCur++) ); - // parse directives - if ( *(pCur-1) != '.' ) - continue; - if ( !strncmp(pCur, "names", 5) ) - Vec_PtrPush( p->pLatest->vNames, pCur ); - else if ( !strncmp(pCur, "latch", 5) ) - Vec_PtrPush( p->pLatest->vLatches, 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 ( !strncmp(pCur, "delay", 5) ) - Vec_PtrPush( p->pLatest->vDelays, pCur ); - else if ( !strncmp(pCur, "input_arrival", 13) ) - Vec_PtrPush( p->pLatest->vArrivals, pCur ); - else if ( !strncmp(pCur, "output_required", 15) ) - Vec_PtrPush( p->pLatest->vRequireds, pCur ); - else if ( !strncmp(pCur, "blackbox", 8) ) - p->pLatest->fBlackBox = 1; - else if ( !strncmp(pCur, "model", 5) ) - { - p->pLatest = Ioa_ReadModAlloc(); - p->pLatest->pFirst = 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", Ioa_ReadGetLine(p, pCur) ); - break; - } - else - { - pCur--; - if ( pCur[strlen(pCur)-1] == '\r' ) - pCur[strlen(pCur)-1] = 0; - fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Ioa_ReadGetLine(p, pCur), pCur ); - } - } -} - -/**Function************************************************************* - - Synopsis [Parses interfaces of the models.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadReadInterfaces( Ioa_ReadMan_t * p ) -{ - Ioa_ReadMod_t * pMod; - char * pLine; - int i, k; - // iterate through the models - Vec_PtrForEachEntry( p->vModels, pMod, i ) - { - // parse the model - if ( !Ioa_ReadParseLineModel( pMod, pMod->pFirst ) ) - return 0; - // parse the inputs - Vec_PtrForEachEntry( pMod->vInputs, pLine, k ) - if ( !Ioa_ReadParseLineInputs( pMod, pLine ) ) - return 0; - // parse the outputs - Vec_PtrForEachEntry( pMod->vOutputs, pLine, k ) - if ( !Ioa_ReadParseLineOutputs( pMod, pLine ) ) - return 0; - // parse the delay info - Vec_PtrForEachEntry( pMod->vDelays, pLine, k ) - if ( !Ioa_ReadParseLineDelay( pMod, pLine ) ) - return 0; - Vec_PtrForEachEntry( pMod->vArrivals, pLine, k ) - if ( !Ioa_ReadParseLineTimes( pMod, pLine, 0 ) ) - return 0; - Vec_PtrForEachEntry( pMod->vRequireds, pLine, k ) - if ( !Ioa_ReadParseLineTimes( pMod, pLine, 1 ) ) - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Ntl_Man_t * Ioa_ReadParse( Ioa_ReadMan_t * p ) -{ - Ntl_Man_t * pDesign; - Ioa_ReadMod_t * pMod; - char * pLine; - int i, k; - // iterate through the models - Vec_PtrForEachEntry( p->vModels, pMod, i ) - { - // parse the latches - Vec_PtrForEachEntry( pMod->vLatches, pLine, k ) - if ( !Ioa_ReadParseLineLatch( pMod, pLine ) ) - return NULL; - // parse the nodes - Vec_PtrForEachEntry( pMod->vNames, pLine, k ) - if ( !Ioa_ReadParseLineNamesBlif( pMod, pLine ) ) - return NULL; - // parse the subcircuits - Vec_PtrForEachEntry( pMod->vSubckts, pLine, k ) - if ( !Ioa_ReadParseLineSubckt( pMod, pLine ) ) - return NULL; - // finalize the network - Ntl_ModelFixNonDrivenNets( pMod->pNtk ); - } - // return the network - pDesign = p->pDesign; - p->pDesign = NULL; - return pDesign; -} - -/**Function************************************************************* - - Synopsis [Parses the model line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadParseLineModel( Ioa_ReadMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry( vTokens, 0 ); - assert( !strcmp(pToken, "model") ); - if ( Vec_PtrSize(vTokens) != 2 ) - { - sprintf( p->pMan->sError, "Line %d: The number of entries in .model line (%d) is different from two.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); - return 0; - } - p->pNtk = Ntl_ModelAlloc( p->pMan->pDesign, Vec_PtrEntry(vTokens, 1) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the inputs line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadParseLineInputs( Ioa_ReadMod_t * p, char * pLine ) -{ - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj; - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - int i; - Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(vTokens, 0); - assert( !strcmp(pToken, "inputs") ); - Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) - { - pObj = Ntl_ModelCreatePi( p->pNtk ); - pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken ); - if ( !Ntl_ModelSetNetDriver( pObj, pNet ) ) - { - sprintf( p->pMan->sError, "Line %d: Net %s already has a driver.", Ioa_ReadGetLine(p->pMan, pToken), pNet->pName ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the outputs line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadParseLineOutputs( Ioa_ReadMod_t * p, char * pLine ) -{ - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj; - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - int i; - Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(vTokens, 0); - assert( !strcmp(pToken, "outputs") ); - Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) - { - pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken ); - pObj = Ntl_ModelCreatePo( p->pNtk, pNet ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the latches line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadParseLineLatch( Ioa_ReadMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Ntl_Net_t * pNetLi, * pNetLo; - Ntl_Obj_t * pObj; - char * pToken, * pNameLi, * pNameLo; - int Init, Class; - Ioa_ReadSplitIntoTokens( 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.", Ioa_ReadGetLine(p->pMan, pToken) ); - return 0; - } - // create latch - pNameLi = Vec_PtrEntry( vTokens, 1 ); - pNameLo = Vec_PtrEntry( vTokens, 2 ); - pNetLi = Ntl_ModelFindOrCreateNet( p->pNtk, pNameLi ); - pNetLo = Ntl_ModelFindOrCreateNet( p->pNtk, pNameLo ); - pObj = Ntl_ModelCreateLatch( p->pNtk ); - pObj->pFanio[0] = pNetLi; - if ( !Ntl_ModelSetNetDriver( pObj, pNetLo ) ) - { - sprintf( p->pMan->sError, "Line %d: Net %s already has a driver.", Ioa_ReadGetLine(p->pMan, pToken), pNetLo->pName ); - return 0; - } - // get initial value - if ( Vec_PtrSize(vTokens) > 3 ) - Init = atoi( Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-1) ); - else - Init = 2; - if ( Init < 0 || Init > 2 ) - { - sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) ); - return 0; - } - // get the register class - if ( Vec_PtrSize(vTokens) == 6 ) - Class = atoi( Vec_PtrEntry(vTokens,3) ); - else - Class = 0; - if ( Class < 0 || Class > (1<<24) ) - { - sprintf( p->pMan->sError, "Line %d: Class of the latch is incorrect \"%s\".", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,4) ); - return 0; - } - pObj->LatchId = (Class << 2) | Init; - // get the clock - if ( Vec_PtrSize(vTokens) == 5 || Vec_PtrSize(vTokens) == 6 ) - { - pToken = Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-2); - pNetLi = Ntl_ModelFindOrCreateNet( p->pNtk, pToken ); - pObj->pFanio[1] = pNetLi; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the subckt line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadParseLineSubckt( Ioa_ReadMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Ntl_Mod_t * pModel; - Ntl_Obj_t * pBox, * pTerm; - Ntl_Net_t * pNet; - char * pToken, * pName, ** ppNames; - int nEquals, i, k; - - // split the line into tokens - nEquals = Ioa_ReadCountChars( pLine, '=' ); - Ioa_ReadSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); - pToken = Vec_PtrEntry(vTokens,0); - assert( !strcmp(pToken, "subckt") ); - - // get the model for this box - pName = Vec_PtrEntry(vTokens,1); - pModel = Ntl_ManFindModel( p->pMan->pDesign, pName ); - if ( pModel == NULL ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Ioa_ReadGetLine(p->pMan, pToken), pName ); - return 0; - } - - // check if the number of tokens is correct - if ( nEquals != Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(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).", - Ioa_ReadGetLine(p->pMan, pToken), nEquals, Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) ); - return 0; - } - - // get the names - ppNames = (char **)Vec_PtrArray(vTokens) + 2; - - // create the box with these terminals - pBox = Ntl_ModelCreateBox( p->pNtk, Ntl_ModelPiNum(pModel), Ntl_ModelPoNum(pModel) ); - pBox->pImplem = pModel; - Ntl_ModelForEachPi( pModel, pTerm, i ) - { - // find this terminal among the formal inputs of the subcircuit - pName = Ntl_ObjFanout0(pTerm)->pName; - 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.", - Ioa_ReadGetLine(p->pMan, pToken), pName, pModel->pName ); - return 0; - } - // create the BI with the actual name - pNet = Ntl_ModelFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); - Ntl_ObjSetFanin( pBox, pNet, i ); - } - Ntl_ModelForEachPo( pModel, pTerm, i ) - { - // find this terminal among the formal outputs of the subcircuit - pName = Ntl_ObjFanin0(pTerm)->pName; - 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 model \"%s\" as a formal output of the subcircuit.", - Ioa_ReadGetLine(p->pMan, pToken), pName, pModel->pName ); - return 0; - } - // create the BI with the actual name - pNet = Ntl_ModelFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); - Ntl_ObjSetFanout( pBox, pNet, i ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the subckt line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadParseLineDelay( Ioa_ReadMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - int RetValue1, RetValue2, Number1, Number2, Temp; - char * pToken, * pTokenNum; - float Delay; - assert( sizeof(float) == sizeof(int) ); - Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(vTokens,0); - assert( !strcmp(pToken, "delay") ); - if ( Vec_PtrSize(vTokens) < 2 && Vec_PtrSize(vTokens) > 4 ) - { - sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (1, 2, or 3).", Ioa_ReadGetLine(p->pMan, pToken) ); - return 0; - } - // find the delay number - pTokenNum = Vec_PtrEntryLast(vTokens); - Delay = atof( pTokenNum ); - if ( Delay == 0.0 && pTokenNum[0] != '0' ) - { - sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntryLast(vTokens) ); - return 0; - } - // find the PI/PO numbers - RetValue1 = 0; Number1 = -1; - if ( Vec_PtrSize(vTokens) > 2 ) - { - RetValue1 = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number1 ); - if ( RetValue1 == 0 ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) ); - return 0; - } - } - RetValue2 = 0; Number2 = -1; - if ( Vec_PtrSize(vTokens) > 3 ) - { - RetValue2 = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 2), &Number2 ); - if ( RetValue2 == 0 ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 2) ); - return 0; - } - } - if ( RetValue1 == RetValue2 && RetValue1 ) - { - sprintf( p->pMan->sError, "Line %d: Both signals \"%s\" and \"%s\" listed appear to be PIs or POs.", - Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1), Vec_PtrEntry(vTokens, 2) ); - return 0; - } - if ( RetValue2 < RetValue1 ) - { - Temp = RetValue2; RetValue2 = RetValue1; RetValue1 = Temp; - Temp = Number2; Number2 = Number1; Number1 = Temp; - } - assert( RetValue1 == 0 || RetValue1 == -1 ); - assert( RetValue2 == 0 || RetValue2 == 1 ); - // store the values - if ( p->pNtk->vDelays == NULL ) - p->pNtk->vDelays = Vec_IntAlloc( 100 ); - Vec_IntPush( p->pNtk->vDelays, Number1 ); - Vec_IntPush( p->pNtk->vDelays, Number2 ); - Vec_IntPush( p->pNtk->vDelays, Aig_Float2Int(Delay) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the subckt line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ioa_ReadParseLineTimes( Ioa_ReadMod_t * p, char * pLine, int fOutput ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - int RetValue, Number; - char * pToken, * pTokenNum; - float Delay; - assert( sizeof(float) == sizeof(int) ); - Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(vTokens,0); - if ( fOutput ) - assert( !strcmp(pToken, "output_required") ); - else - assert( !strcmp(pToken, "input_arrival") ); - if ( Vec_PtrSize(vTokens) != 3 ) - { - sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (3).", Ioa_ReadGetLine(p->pMan, pToken) ); - return 0; - } - // find the delay number - pTokenNum = Vec_PtrEntryLast(vTokens); - if ( !strcmp( pTokenNum, "-inf" ) ) - Delay = -AIG_INFINITY; - else if ( !strcmp( pTokenNum, "inf" ) ) - Delay = AIG_INFINITY; - else - Delay = atof( pTokenNum ); - if ( Delay == 0.0 && pTokenNum[0] != '0' ) - { - sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntryLast(vTokens) ); - return 0; - } - // find the PI/PO numbers - if ( fOutput ) - { - RetValue = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number ); - if ( RetValue == 0 ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) ); - return 0; - } - // store the values - if ( p->pNtk->vRequireds == NULL ) - p->pNtk->vRequireds = Vec_IntAlloc( 100 ); - Vec_IntPush( p->pNtk->vRequireds, Number ); - Vec_IntPush( p->pNtk->vRequireds, Aig_Float2Int(Delay) ); - } - else - { - RetValue = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number ); - if ( RetValue == 0 ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) ); - return 0; - } - // store the values - if ( p->pNtk->vArrivals == NULL ) - p->pNtk->vArrivals = Vec_IntAlloc( 100 ); - Vec_IntPush( p->pNtk->vArrivals, Number ); - Vec_IntPush( p->pNtk->vArrivals, Aig_Float2Int(Delay) ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Constructs the SOP cover from the file parsing info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Ioa_ReadParseTableBlif( Ioa_ReadMod_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 - Ioa_ReadSplitIntoTokens( vTokens, pTable, '.' ); - if ( Vec_PtrSize(vTokens) == 0 ) - return Ntl_ManStoreSop( p->pMan->pDesign, " 0\n" ); - 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\".", Ioa_ReadGetLine(p->pMan, pOutput), pOutput ); - return NULL; - } - return Ntl_ManStoreSop( p->pMan->pDesign, (pOutput[0] == '0') ? " 0\n" : " 1\n" ); - } - pProduct = Vec_PtrEntry( vTokens, 0 ); - if ( Vec_PtrSize(vTokens) % 2 == 1 ) - { - sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Ioa_ReadGetLine(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).", Ioa_ReadGetLine(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.", Ioa_ReadGetLine(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).", Ioa_ReadGetLine(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 Ioa_ReadParseLineNamesBlif( Ioa_ReadMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Ntl_Obj_t * pNode; - Ntl_Net_t * pNetOut, * pNetIn; - char * pNameOut, * pNameIn; - int i; - Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - // parse the mapped node -// if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") ) -// return Ioa_ReadParseLineGateBlif( p, vTokens ); - // parse the regular name line - assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") ); - pNameOut = Vec_PtrEntryLast( vTokens ); -/* - if ( strcmp( pNameOut, "18434" ) == 0 ) - { - int x = 0; - } -*/ - pNetOut = Ntl_ModelFindOrCreateNet( p->pNtk, pNameOut ); - // create fanins - pNode = Ntl_ModelCreateNode( p->pNtk, Vec_PtrSize(vTokens) - 2 ); - for ( i = 0; i < Vec_PtrSize(vTokens) - 2; i++ ) - { - pNameIn = Vec_PtrEntry(vTokens, i+1); - pNetIn = Ntl_ModelFindOrCreateNet( p->pNtk, pNameIn ); - Ntl_ObjSetFanin( pNode, pNetIn, i ); - } - if ( !Ntl_ModelSetNetDriver( pNode, pNetOut ) ) - { - sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Ioa_ReadGetLine(p->pMan, pNameOut), pNameOut ); - return 0; - } - // parse the table of this node - pNode->pSop = Ioa_ReadParseTableBlif( p, pNameOut + strlen(pNameOut), pNode->nFanins ); - if ( pNode->pSop == NULL ) - return 0; - pNode->pSop = Ntl_ManStoreSop( p->pNtk->pMan, pNode->pSop ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlTable.c b/src/aig/ntl/ntlTable.c deleted file mode 100644 index b84ac1a5..00000000 --- a/src/aig/ntl/ntlTable.c +++ /dev/null @@ -1,217 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Name table manipulation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing for strings -static unsigned Ntl_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; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates memory for the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Net_t * Ntl_ModelCreateNet( Ntl_Mod_t * p, char * pName ) -{ - Ntl_Net_t * pNet; - pNet = (Ntl_Net_t *)Aig_MmFlexEntryFetch( p->pMan->pMemObjs, sizeof(Ntl_Net_t) + strlen(pName) + 1 ); - memset( pNet, 0, sizeof(Ntl_Net_t) ); - strcpy( pNet->pName, pName ); - return pNet; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelTableResize( Ntl_Mod_t * p ) -{ - Ntl_Net_t ** pTableNew, ** ppSpot, * pEntry, * pEntry2; - int nTableSizeNew, Counter, e, clk; -clk = clock(); - // get the new table size - nTableSizeNew = Aig_PrimeCudd( 3 * p->nTableSize ); - // allocate a new array - pTableNew = ALLOC( Ntl_Net_t *, nTableSizeNew ); - memset( pTableNew, 0, sizeof(Ntl_Net_t *) * nTableSizeNew ); - // rehash entries - Counter = 0; - for ( e = 0; e < p->nTableSize; e++ ) - for ( pEntry = p->pTable[e], pEntry2 = pEntry? pEntry->pNext : NULL; - pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNext : NULL ) - { - ppSpot = pTableNew + Ntl_HashString( pEntry->pName, nTableSizeNew ); - pEntry->pNext = *ppSpot; - *ppSpot = pEntry; - Counter++; - } - assert( Counter == p->nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", p->nTableSize, nTableSizeNew ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( p->pTable ); - p->pTable = pTableNew; - p->nTableSize = nTableSizeNew; -} - -/**Function************************************************************* - - Synopsis [Finds or creates the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, char * pName ) -{ - Ntl_Net_t * pEnt; - unsigned Key = Ntl_HashString( pName, p->nTableSize ); - for ( pEnt = p->pTable[Key]; pEnt; pEnt = pEnt->pNext ) - if ( !strcmp( pEnt->pName, pName ) ) - return pEnt; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Finds or creates the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, char * pName ) -{ - Ntl_Net_t * pEnt; - unsigned Key = Ntl_HashString( pName, p->nTableSize ); - for ( pEnt = p->pTable[Key]; pEnt; pEnt = pEnt->pNext ) - if ( !strcmp( pEnt->pName, pName ) ) - return pEnt; - pEnt = Ntl_ModelCreateNet( p, pName ); - pEnt->pNext = p->pTable[Key]; - p->pTable[Key] = pEnt; - if ( ++p->nEntries > 2 * p->nTableSize ) - Ntl_ModelTableResize( p ); - return pEnt; -} - -/**Function************************************************************* - - Synopsis [Finds or creates the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ) -{ - if ( pObj->pFanio[pObj->nFanins] != NULL ) - return 0; - if ( pNet->pDriver != NULL ) - return 0; - pObj->pFanio[pObj->nFanins] = pNet; - pNet->pDriver = pObj; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns -1, 0, +1 (when it is PI, not found, or PO).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, char * pName, int * pNumber ) -{ - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj; - int i; - *pNumber = -1; - pNet = Ntl_ModelFindNet( p, pName ); - if ( pNet == NULL ) - return 0; - Ntl_ModelForEachPo( p, pObj, i ) - { - if ( Ntl_ObjFanin0(pObj) == pNet ) - { - *pNumber = i; - return 1; - } - } - Ntl_ModelForEachPi( p, pObj, i ) - { - if ( Ntl_ObjFanout0(pObj) == pNet ) - { - *pNumber = i; - return -1; - } - } - return 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlTime.c b/src/aig/ntl/ntlTime.c deleted file mode 100644 index 50f3d290..00000000 --- a/src/aig/ntl/ntlTime.c +++ /dev/null @@ -1,128 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlTime.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Creates timing manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlTime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float * Ntl_ManCreateDelayTable( Vec_Int_t * vDelays, int nIns, int nOuts ) -{ - float * pDelayTable, Delay; - int iIn, iOut, i, k; - assert( Vec_IntSize(vDelays) % 3 == 0 ); - pDelayTable = ALLOC( float, nIns * nOuts ); - memset( pDelayTable, 0, sizeof(float) * nIns * nOuts ); - Vec_IntForEachEntry( vDelays, iIn, i ) - { - iOut = Vec_IntEntry(vDelays, ++i); - Delay = Aig_Int2Float( Vec_IntEntry(vDelays, ++i) ); - if ( iIn == -1 && iOut == -1 ) - for ( k = 0; k < nIns * nOuts; k++ ) - pDelayTable[k] = Delay; - else if ( iIn == -1 ) - for ( k = 0; k < nIns; k++ ) - pDelayTable[iOut * nIns + k] = Delay; - else if ( iOut == -1 ) - for ( k = 0; k < nOuts; k++ ) - pDelayTable[k * nIns + iIn] = Delay; - else - pDelayTable[iOut * nIns + iIn] = Delay; - } - return pDelayTable; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Tim_Man_t * Ntl_ManCreateTiming( Ntl_Man_t * p ) -{ - Tim_Man_t * pMan; - Vec_Ptr_t * vDelayTables; - Ntl_Mod_t * pRoot, * pModel; - Ntl_Obj_t * pObj; - int i, curPi, iBox, Entry; - assert( p->pAig != NULL ); - pRoot = Vec_PtrEntry( p->vModels, 0 ); - // start the timing manager - pMan = Tim_ManStart( Aig_ManPiNum(p->pAig), Aig_ManPoNum(p->pAig) ); - // unpack the data in the arrival times - if ( pRoot->vArrivals ) - Vec_IntForEachEntry( pRoot->vArrivals, Entry, i ) - Tim_ManInitPiArrival( pMan, Entry, Aig_Int2Float(Vec_IntEntry(pRoot->vArrivals,++i)) ); - // unpack the data in the required times - if ( pRoot->vRequireds ) - Vec_IntForEachEntry( pRoot->vRequireds, Entry, i ) - Tim_ManInitPoRequired( pMan, Entry, Aig_Int2Float(Vec_IntEntry(pRoot->vRequireds,++i)) ); - // derive timing tables - vDelayTables = Vec_PtrAlloc( Vec_PtrSize(p->vModels) ); - Ntl_ManForEachModel( p, pModel, i ) - { - if ( pModel->vDelays ) - pModel->pDelayTable = Ntl_ManCreateDelayTable( pModel->vDelays, Ntl_ModelPiNum(pModel), Ntl_ModelPoNum(pModel) ); - Vec_PtrPush( vDelayTables, pModel->pDelayTable ); - } - Tim_ManSetDelayTables( pMan, vDelayTables ); - // set up the boxes - iBox = 0; - curPi = Ntl_ModelCiNum(pRoot); - Ntl_ManForEachBox( p, pObj, i ) - { - Tim_ManCreateBoxFirst( pMan, Vec_IntEntry(p->vBox1Cos, iBox), Ntl_ObjFaninNum(pObj), curPi, Ntl_ObjFanoutNum(pObj), pObj->pImplem->pDelayTable ); - curPi += Ntl_ObjFanoutNum(pObj); - iBox++; - } - // forget refs to the delay tables in the network - Ntl_ManForEachModel( p, pModel, i ) - pModel->pDelayTable = NULL; -// Tim_ManPrint( pMan ); - return pMan; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntlWriteBlif.c b/src/aig/ntl/ntlWriteBlif.c deleted file mode 100644 index 8bcd2044..00000000 --- a/src/aig/ntl/ntlWriteBlif.c +++ /dev/null @@ -1,127 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlWriteBlif.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: ntlWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "ioa.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes one model into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ioa_WriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel ) -{ - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - int i, k; - fprintf( pFile, ".model %s\n", pModel->pName ); - fprintf( pFile, ".inputs" ); - Ntl_ModelForEachPi( pModel, pObj, i ) - fprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".outputs" ); - Ntl_ModelForEachPo( pModel, pObj, i ) - fprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName ); - fprintf( pFile, "\n" ); - Ntl_ModelForEachObj( pModel, pObj, i ) - { - if ( Ntl_ObjIsNode(pObj) ) - { - fprintf( pFile, ".names" ); - Ntl_ObjForEachFanin( pObj, pNet, k ) - fprintf( pFile, " %s", pNet->pName ); - fprintf( pFile, " %s\n", Ntl_ObjFanout0(pObj)->pName ); - fprintf( pFile, "%s", pObj->pSop ); - } - else if ( Ntl_ObjIsLatch(pObj) ) - { - fprintf( pFile, ".latch" ); - fprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName ); - fprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName ); - if ( pObj->LatchId >> 2 ) - fprintf( pFile, " %d", pObj->LatchId >> 2 ); - if ( pObj->pFanio[1] != NULL ) - fprintf( pFile, " %s", Ntl_ObjFanin(pObj, 1)->pName ); - fprintf( pFile, " %d", pObj->LatchId & 3 ); - fprintf( pFile, "\n" ); - } - else if ( Ntl_ObjIsBox(pObj) ) - { - fprintf( pFile, ".subckt %s", pObj->pImplem->pName ); - Ntl_ObjForEachFanin( pObj, pNet, k ) - fprintf( pFile, " %s=%s", Ntl_ModelPiName(pObj->pImplem, k), pNet->pName ); - Ntl_ObjForEachFanout( pObj, pNet, k ) - fprintf( pFile, " %s=%s", Ntl_ModelPoName(pObj->pImplem, k), pNet->pName ); - fprintf( pFile, "\n" ); - } - } - fprintf( pFile, ".end\n\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the network into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Ntl_Mod_t * pModel; - int i; - // start the output stream - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Ioa_WriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - fprintf( pFile, "# Benchmark \"%s\" written by ABC-8 on %s\n", p->pName, Ioa_TimeStamp() ); - // write the models - Ntl_ManForEachModel( p, pModel, i ) - Ioa_WriteBlifModel( pFile, pModel ); - // close the file - fclose( pFile ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ntl/ntl_.c b/src/aig/ntl/ntl_.c deleted file mode 100644 index 4b3ad684..00000000 --- a/src/aig/ntl/ntl_.c +++ /dev/null @@ -1,47 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntl_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntl_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - 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/aig/tim/module.make b/src/aig/tim/module.make deleted file mode 100644 index 81079346..00000000 --- a/src/aig/tim/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/aig/tim/tim.c diff --git a/src/aig/tim/tim.c b/src/aig/tim/tim.c deleted file mode 100644 index 8d312dba..00000000 --- a/src/aig/tim/tim.c +++ /dev/null @@ -1,532 +0,0 @@ -/**CFile**************************************************************** - - FileName [tim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [A timing manager.] - - Synopsis [Representation of timing information.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: tim.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include - -#include "vec.h" -#include "mem.h" -#include "tim.h" - -#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) - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Tim_Box_t_ Tim_Box_t; -typedef struct Tim_Obj_t_ Tim_Obj_t; - -// timing manager -struct Tim_Man_t_ -{ - Vec_Ptr_t * vBoxes; // the timing boxes - Vec_Ptr_t * vDelayTables; // pointers to the delay tables - Mem_Flex_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 - Tim_Obj_t * pPis; // timing info for the PIs - Tim_Obj_t * pPos; // timing info for the POs -}; - -// timing box -struct Tim_Box_t_ -{ - int iBox; // the unique ID of this box - int TravId; // traversal ID of this box - int nInputs; // the number of box inputs (POs) - int nOutputs; // the number of box outputs (PIs) - float * pDelayTable; // delay for each input->output path - int Inouts[0]; // the int numbers of PIs and POs -}; - -// timing object -struct Tim_Obj_t_ -{ - int Id; // the ID of this object - int TravId; // traversal ID of this object - int iObj2Box; // mapping of the object into its box - int iObj2Num; // mapping of the object into its number in the box - float timeArr; // arrival time of the object - float timeReq; // required time of the object -}; - -static inline Tim_Obj_t * Tim_ManPi( Tim_Man_t * p, int i ) { assert( i < p->nPis ); return p->pPis + i; } -static inline Tim_Obj_t * Tim_ManPo( Tim_Man_t * p, int i ) { assert( i < p->nPos ); return p->pPos + i; } - -static inline Tim_Box_t * Tim_ManPiBox( Tim_Man_t * p, int i ) { return Tim_ManPi(p,i)->iObj2Box < 0 ? NULL : Vec_PtrEntry( p->vBoxes, Tim_ManPi(p,i)->iObj2Box ); } -static inline Tim_Box_t * Tim_ManPoBox( Tim_Man_t * p, int i ) { return Tim_ManPo(p,i)->iObj2Box < 0 ? NULL : Vec_PtrEntry( p->vBoxes, Tim_ManPo(p,i)->iObj2Box ); } - -static inline Tim_Obj_t * Tim_ManBoxInput( Tim_Man_t * p, Tim_Box_t * pBox, int i ) { assert( i < pBox->nInputs ); return p->pPos + pBox->Inouts[i]; } -static inline Tim_Obj_t * Tim_ManBoxOutput( Tim_Man_t * p, Tim_Box_t * pBox, int i ) { assert( i < pBox->nOutputs ); return p->pPis + pBox->Inouts[pBox->nInputs+i]; } - -#define Tim_ManBoxForEachInput( p, pBox, pObj, i ) \ - for ( i = 0; (i < (pBox)->nInputs) && ((pObj) = Tim_ManBoxInput(p, pBox, i)); i++ ) -#define Tim_ManBoxForEachOutput( p, pBox, pObj, i ) \ - for ( i = 0; (i < (pBox)->nOutputs) && ((pObj) = Tim_ManBoxOutput(p, pBox, i)); i++ ) - -#define Tim_ManForEachPi( p, pObj, i ) \ - for ( i = 0; (i < (p)->nPis) && ((pObj) = (p)->pPis + i); i++ ) \ - if ( pObj->iObj2Box >= 0 ) {} else -#define Tim_ManForEachPo( p, pObj, i ) \ - for ( i = 0; (i < (p)->nPos) && ((pObj) = (p)->pPos + i); i++ ) \ - if ( pObj->iObj2Box >= 0 ) {} else -#define Tim_ManForEachBox( p, pBox, i ) \ - Vec_PtrForEachEntry( p->vBoxes, pBox, i ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the timing manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Tim_Man_t * Tim_ManStart( int nPis, int nPos ) -{ - Tim_Man_t * p; - int i; - p = ALLOC( Tim_Man_t, 1 ); - memset( p, 0, sizeof(Tim_Man_t) ); - p->pMemObj = Mem_FlexStart(); - p->vBoxes = Vec_PtrAlloc( 100 ); - p->nPis = nPis; - p->nPos = nPos; - p->pPis = ALLOC( Tim_Obj_t, nPis ); - memset( p->pPis, 0, sizeof(Tim_Obj_t) * nPis ); - p->pPos = ALLOC( Tim_Obj_t, nPos ); - memset( p->pPos, 0, sizeof(Tim_Obj_t) * nPos ); - for ( i = 0; i < nPis; i++ ) - { - p->pPis[i].Id = i; - p->pPis[i].iObj2Box = p->pPis[i].iObj2Num = -1; - p->pPis[i].timeReq = AIG_INFINITY; - p->pPis[i].timeArr = 0.0; - p->pPis[i].TravId = 0; - } - for ( i = 0; i < nPos; i++ ) - { - p->pPos[i].Id = i; - p->pPos[i].iObj2Box = p->pPos[i].iObj2Num = -1; - p->pPos[i].timeReq = AIG_INFINITY; - p->pPos[i].timeArr = 0.0; - p->pPos[i].TravId = 0; - } - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the timing manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManStop( Tim_Man_t * p ) -{ - float * pTable; - int i; - if ( p->vDelayTables ) - { - Vec_PtrForEachEntry( p->vDelayTables, pTable, i ) - FREE( pTable ); - Vec_PtrFree( p->vDelayTables ); - } - Vec_PtrFree( p->vBoxes ); - Mem_FlexStop( p->pMemObj, 0 ); - free( p->pPis ); - free( p->pPos ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Stops the timing manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManPrint( Tim_Man_t * p ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObj; - int i; - printf( "TIMING INFORMATION:\n" ); - Tim_ManForEachPi( p, pObj, i ) - printf( "pi%5d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq ); - Tim_ManForEachPo( p, pObj, i ) - printf( "po%5d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq ); - Tim_ManForEachBox( p, pBox, i ) - { - printf( "*** Box %3d : Ins = %d. Outs = %d.\n", i, pBox->nInputs, pBox->nOutputs ); - printf( "Delay table:" ); - for ( i = 0; i < pBox->nInputs * pBox->nOutputs; i++ ) - printf( " %5.3f", pBox->pDelayTable[i] ); - printf( "\n" ); - Tim_ManBoxForEachInput( p, pBox, pObj, i ) - printf( "box-inp%3d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq ); - Tim_ManBoxForEachOutput( p, pBox, pObj, i ) - printf( "box-out%3d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Sets the vector of timing tables associated with the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables ) -{ - assert( p->vDelayTables == NULL ); - p->vDelayTables = vDelayTables; -} - -/**Function************************************************************* - - Synopsis [Creates the new timing box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManCreateBox( Tim_Man_t * p, int * pIns, int nIns, int * pOuts, int nOuts, float * pDelayTable ) -{ - Tim_Box_t * pBox; - int i; - pBox = (Tim_Box_t *)Mem_FlexEntryFetch( p->pMemObj, sizeof(Tim_Box_t) + sizeof(int) * (nIns+nOuts) ); - memset( pBox, 0, sizeof(Tim_Box_t) ); - pBox->iBox = Vec_PtrSize( p->vBoxes ); - Vec_PtrPush( p->vBoxes, pBox ); - pBox->pDelayTable = pDelayTable; - pBox->nInputs = nIns; - pBox->nOutputs = nOuts; - for ( i = 0; i < nIns; i++ ) - { - assert( pIns[i] < p->nPos ); - pBox->Inouts[i] = pIns[i]; - p->pPos[pIns[i]].iObj2Box = pBox->iBox; - p->pPos[pIns[i]].iObj2Num = i; - } - for ( i = 0; i < nOuts; i++ ) - { - assert( pOuts[i] < p->nPis ); - pBox->Inouts[nIns+i] = pOuts[i]; - p->pPis[pOuts[i]].iObj2Box = pBox->iBox; - p->pPis[pOuts[i]].iObj2Num = i; - } -} - -/**Function************************************************************* - - Synopsis [Creates the new timing box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManCreateBoxFirst( Tim_Man_t * p, int firstIn, int nIns, int firstOut, int nOuts, float * pDelayTable ) -{ - Tim_Box_t * pBox; - int i; - pBox = (Tim_Box_t *)Mem_FlexEntryFetch( p->pMemObj, sizeof(Tim_Box_t) + sizeof(int) * (nIns+nOuts) ); - memset( pBox, 0, sizeof(Tim_Box_t) ); - pBox->iBox = Vec_PtrSize( p->vBoxes ); - Vec_PtrPush( p->vBoxes, pBox ); - pBox->pDelayTable = pDelayTable; - pBox->nInputs = nIns; - pBox->nOutputs = nOuts; - for ( i = 0; i < nIns; i++ ) - { - assert( firstIn+i < p->nPos ); - pBox->Inouts[i] = firstIn+i; - p->pPos[firstIn+i].iObj2Box = pBox->iBox; - p->pPos[firstIn+i].iObj2Num = i; - } - for ( i = 0; i < nOuts; i++ ) - { - assert( firstOut+i < p->nPis ); - pBox->Inouts[nIns+i] = firstOut+i; - p->pPis[firstOut+i].iObj2Box = pBox->iBox; - p->pPis[firstOut+i].iObj2Num = i; - } -} - - - -/**Function************************************************************* - - Synopsis [Increments the trav ID of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManIncrementTravId( Tim_Man_t * p ) -{ - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Initializes arrival time of the PI.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManInitPiArrival( Tim_Man_t * p, int iPi, float Delay ) -{ - assert( iPi < p->nPis ); - p->pPis[iPi].timeArr = Delay; -} - -/**Function************************************************************* - - Synopsis [Initializes required time of the PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManInitPoRequired( Tim_Man_t * p, int iPo, float Delay ) -{ - assert( iPo < p->nPos ); - p->pPos[iPo].timeReq = Delay; -} - -/**Function************************************************************* - - Synopsis [Updates required time of the PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetPoArrival( Tim_Man_t * p, int iPo, float Delay ) -{ - assert( iPo < p->nPos ); - assert( p->pPos[iPo].TravId != p->nTravIds ); - p->pPos[iPo].timeArr = Delay; - p->pPos[iPo].TravId = p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Updates arrival time of the PI.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetPiRequired( Tim_Man_t * p, int iPi, float Delay ) -{ - assert( iPi < p->nPis ); - assert( p->pPis[iPi].TravId != p->nTravIds ); - p->pPis[iPi].timeReq = Delay; - p->pPis[iPi].TravId = p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Updates required time of the PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetPoRequired( Tim_Man_t * p, int iPo, float Delay ) -{ - assert( iPo < p->nPos ); - assert( p->pPos[iPo].TravId != p->nTravIds ); - p->pPos[iPo].timeReq = Delay; - p->pPos[iPo].TravId = p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Sets the correct required times for all POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetPoRequiredAll( Tim_Man_t * p, float Delay ) -{ - Tim_Obj_t * pObj; - int i; - Tim_ManForEachPo( p, pObj, i ) - Tim_ManSetPoRequired( p, i, Delay ); -} - - -/**Function************************************************************* - - Synopsis [Returns PI arrival time.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Tim_ManGetPiArrival( Tim_Man_t * p, int iPi ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObjThis, * pObj, * pObjRes; - float * pDelays, DelayBest; - int i, k; - // consider the already processed PI - pObjThis = Tim_ManPi( p, iPi ); - if ( pObjThis->TravId == p->nTravIds ) - return pObjThis->timeArr; - pObjThis->TravId = p->nTravIds; - // consider the main PI - pBox = Tim_ManPiBox( p, iPi ); - if ( pBox == NULL ) - return pObjThis->timeArr; - // update box timing - pBox->TravId = p->nTravIds; - // get the arrival times of the inputs of the box (POs) - Tim_ManBoxForEachInput( p, pBox, pObj, i ) - if ( pObj->TravId != p->nTravIds ) - printf( "Tim_ManGetPiArrival(): PO arrival times of the box are not up to date!\n" ); - // compute the arrival times for each output of the box (PIs) - Tim_ManBoxForEachOutput( p, pBox, pObjRes, i ) - { - pDelays = pBox->pDelayTable + i * pBox->nInputs; - DelayBest = -AIG_INFINITY; - Tim_ManBoxForEachInput( p, pBox, pObj, k ) - DelayBest = AIG_MAX( DelayBest, pObj->timeArr + pDelays[k] ); - pObjRes->timeArr = DelayBest; - pObjRes->TravId = p->nTravIds; - } - return pObjThis->timeArr; -} - -/**Function************************************************************* - - Synopsis [Returns PO required time.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Tim_ManGetPoRequired( Tim_Man_t * p, int iPo ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObjThis, * pObj, * pObjRes; - float * pDelays, DelayBest; - int i, k; - // consider the already processed PO - pObjThis = Tim_ManPo( p, iPo ); - if ( pObjThis->TravId == p->nTravIds ) - return pObjThis->timeReq; - pObjThis->TravId = p->nTravIds; - // consider the main PO - pBox = Tim_ManPoBox( p, iPo ); - if ( pBox == NULL ) - return pObjThis->timeReq; - // update box timing - pBox->TravId = p->nTravIds; - // get the required times of the inputs of the box (POs) - Tim_ManBoxForEachOutput( p, pBox, pObj, i ) - if ( pObj->TravId != p->nTravIds ) - printf( "Tim_ManGetPoRequired(): PI required times of the box are not up to date!\n" ); - // compute the required times for each output of the box (PIs) - Tim_ManBoxForEachInput( p, pBox, pObjRes, i ) - { - DelayBest = AIG_INFINITY; - Tim_ManBoxForEachOutput( p, pBox, pObj, k ) - { - pDelays = pBox->pDelayTable + k * pBox->nInputs; - DelayBest = AIG_MIN( DelayBest, pObj->timeReq - pDelays[i] ); - } - pObjRes->timeReq = DelayBest; - pObjRes->TravId = p->nTravIds; - } - return pObjThis->timeReq; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/tim/tim.h b/src/aig/tim/tim.h deleted file mode 100644 index d7544169..00000000 --- a/src/aig/tim/tim.h +++ /dev/null @@ -1,85 +0,0 @@ -/**CFile**************************************************************** - - FileName [tim.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [A timing manager.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: tim.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __TIM_H__ -#define __TIM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Tim_Man_t_ Tim_Man_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// SEQUENTIAL ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== time.c ===========================================================*/ -extern Tim_Man_t * Tim_ManStart( int nPis, int nPos ); -extern void Tim_ManStop( Tim_Man_t * p ); -extern void Tim_ManPrint( Tim_Man_t * p ); -extern void Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables ); -extern void Tim_ManCreateBox( Tim_Man_t * p, int * pIns, int nIns, int * pOuts, int nOuts, float * pDelayTable ); -extern void Tim_ManCreateBoxFirst( Tim_Man_t * p, int firstIn, int nIns, int firstOut, int nOuts, float * pDelayTable ); -extern void Tim_ManIncrementTravId( Tim_Man_t * p ); -extern void Tim_ManInitPiArrival( Tim_Man_t * p, int iPi, float Delay ); -extern void Tim_ManInitPoRequired( Tim_Man_t * p, int iPo, float Delay ); -extern void Tim_ManSetPoArrival( Tim_Man_t * p, int iPo, float Delay ); -extern void Tim_ManSetPiRequired( Tim_Man_t * p, int iPi, float Delay ); -extern void Tim_ManSetPoRequired( Tim_Man_t * p, int iPo, float Delay ); -extern void Tim_ManSetPoRequiredAll( Tim_Man_t * p, float Delay ); -extern float Tim_ManGetPiArrival( Tim_Man_t * p, int iPi ); -extern float Tim_ManGetPoRequired( Tim_Man_t * p, int iPo ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/abc/1.txt b/src/base/abc/1.txt deleted file mode 100644 index c0765c2b..00000000 --- a/src/base/abc/1.txt +++ /dev/null @@ -1,21 +0,0 @@ -Comparing files abcDfs.c and C:\_PROJECTS\AARON\FRETIME\SRC\BASE\ABC\ABCDFS.C -***** abcDfs.c - return pNode->Level; - assert( Abc_ObjIsNode( pNode ) ); - // if this node is already visited, return -***** C:\_PROJECTS\AARON\FRETIME\SRC\BASE\ABC\ABCDFS.C - return pNode->Level; - assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1); - // if this node is already visited, return -***** - -***** abcDfs.c - return pNode->Level; - assert( Abc_ObjIsNode( pNode ) ); - // if this node is already visited, return -***** C:\_PROJECTS\AARON\FRETIME\SRC\BASE\ABC\ABCDFS.C - return pNode->Level; - assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1); - // if this node is already visited, return -***** - diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 11161698..aea5a62d 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -21,10 +21,6 @@ #ifndef __ABC_H__ #define __ABC_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -36,11 +32,10 @@ extern "C" { #include #include "cuddInt.h" -#include "hop.h" #include "extra.h" +#include "solver.h" #include "vec.h" #include "stmm.h" -#include "nm.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -48,235 +43,181 @@ extern "C" { // 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_TYPE_NONE, // 0: unknown + ABC_TYPE_NETLIST, // 1: network with PIs/POs, latches, nodes, and nets + ABC_TYPE_LOGIC, // 2: network with PIs/POs, latches, and nodes + ABC_TYPE_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges) + ABC_TYPE_SEQ, // 4: sequential AIG (two input AND gates with c- and latch-attributes on edges) + ABC_TYPE_OTHER // 5: unused } Abc_NtkType_t; // network functionality typedef enum { - ABC_FUNC_NONE = 0, // 0: unknown + ABC_FUNC_NONE, // 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_FUNC_OTHER // 5: unused } Abc_NtkFunc_t; // Supported type/functionality combinations: /*------------------------------------------| | | SOP | BDD | AIG | Map | |-----------|-------|-------|-------|-------| -| Netlist | x | | x | x | +| Netlist | x | | | x | |-----------|-------|-------|-------|-------| -| Logic | x | x | x | x | +| Logic | x | x | | x | |-----------|-------|-------|-------|-------| | Strash | | | x | | +|-----------|-------|-------|-------|-------| +| Seq | | | 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_OBJ_NONE, // 0: unknown + ABC_OBJ_NET, // 1: net + ABC_OBJ_NODE, // 2: node + ABC_OBJ_LATCH, // 3: latch + ABC_OBJ_PI, // 4: primary input terminal + ABC_OBJ_PO, // 5: primary output terminal + ABC_OBJ_OTHER // 6: 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 -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; +typedef struct Abc_Obj_t_ Abc_Obj_t; +typedef struct Abc_Ntk_t_ Abc_Ntk_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; + 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) + Abc_Ntk_t * pNtk; // the host network + unsigned Type : 4; // the object type + unsigned fExor : 1; // marks AIG node that is a root of EXOR + unsigned Id : 27; // the ID of the object // 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 + 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 TravId : 12; // the traversal ID + unsigned Level : 16; // the level of the node // connectivity - Vec_Int_t vFanins; // the array of fanins - Vec_Int_t vFanouts; // the array of fanouts + Vec_Fan_t vFanins; // the array of fanins + Vec_Fan_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 + 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 }; 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) + 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 + // name representation + stmm_table * tName2Net; // the table hashing net names into net pointer + stmm_table * tObj2Name; // the table hashing PI/PO/latch pointers into names // 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 + Vec_Ptr_t * vObjs; // the array of all objects (net, nodes, latches) + Vec_Ptr_t * vCis; // the array of combinational inputs (PIs followed by latches) + Vec_Ptr_t * vCos; // the array of combinational outputs (POs followed by latches) + Vec_Ptr_t * vLats; // the array of latches (or the cutset in the sequential network) + // the stats about the number of living objects + int nObjs; // the number of living objs + int nNets; // the number of living nets + int nNodes; // the number of living nodes + int nLatches; // the number of latches + int nPis; // the number of primary inputs + int nPos; // the number of primary outputs + // the functionality manager + void * pManFunc; // AIG manager, BDD manager, or memory manager for SOPs + // the global functions (BDDs) + void * pManGlob; // the BDD manager + Vec_Ptr_t * vFuncsGlob; // the BDDs of CO functions + // the timing manager (for mapped networks) + Abc_ManTime_t * pManTime; // stores arrival/required times for all nodes + // the cut manager (for AIGs) + void * pManCut; // stores information about the cuts computed for the nodes + // level information (for AIGs) + int LevelMax; // maximum number of levels + Vec_Int_t * vLevelsR; // level in the reverse topological order + // support information + Vec_Ptr_t * vSupps; + // the external don't-care if given + Abc_Ntk_t * pExdc; // the EXDC network // 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) - void * pSeqModel; // counter-example (for sequential 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 + unsigned nTravIds; // the unique traversal IDs of nodes + Vec_Ptr_t * vPtrTemp; // the temporary array + Vec_Int_t * vIntTemp; // the temporary array + Vec_Str_t * vStrTemp; // the temporary array + void * pData; // the temporary pointer + // 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 + // memory management + Extra_MmFlex_t * pMmNames; // memory manager for net names + Extra_MmFixed_t* pMmObj; // memory manager for objects + Extra_MmStep_t * pMmStep; // memory manager for arrays }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // 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; } +#define ABC_INFINITY (10000000) // 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 ; } +static inline bool Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_TYPE_NETLIST; } +static inline bool Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_TYPE_LOGIC; } +static inline bool Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_TYPE_STRASH; } +static inline bool Abc_NtkIsSeq( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_TYPE_SEQ; } + +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_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_TYPE_NETLIST; } +static inline bool Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_TYPE_NETLIST; } +static inline bool Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_TYPE_LOGIC ; } +static inline bool Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_TYPE_LOGIC ; } +static inline bool Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_TYPE_LOGIC ; } +static inline bool Abc_NtkIsComb( Abc_Ntk_t * pNtk ) { return pNtk->nLatches == 0; } // 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; } +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; } @@ -285,127 +226,106 @@ static inline void Abc_NtkSetBackup( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNetBa 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 ); } +static inline int Abc_NtkObjNumMax( Abc_Ntk_t * pNtk ) { return pNtk->vObjs->nSize; } +static inline int Abc_NtkObjNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjs; } +static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nNets; } +static inline int Abc_NtkNodeNum( Abc_Ntk_t * pNtk ) { return pNtk->nNodes; } +static inline int Abc_NtkLatchNum( Abc_Ntk_t * pNtk ) { return pNtk->nLatches; } +static inline int Abc_NtkPiNum( Abc_Ntk_t * pNtk ) { return pNtk->nPis; } +static inline int Abc_NtkPoNum( Abc_Ntk_t * pNtk ) { return pNtk->nPos; } +static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return pNtk->vCis->nSize; } +static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return pNtk->vCos->nSize; } // 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)); } +static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i ) { assert( i < Vec_PtrSize(pNtk->vObjs) ); return pNtk->vObjs->pArray[i]; } +static inline Abc_Obj_t * Abc_NtkLatch( Abc_Ntk_t * pNtk, int i ) { assert( i < Vec_PtrSize(pNtk->vLats) ); return pNtk->vLats->pArray[i]; } +static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i ) { assert( i < Abc_NtkPiNum(pNtk) ); return pNtk->vCis->pArray[i]; } +static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i ) { assert( i < Abc_NtkPoNum(pNtk) ); return pNtk->vCos->pArray[i]; } +static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { assert( i < Abc_NtkCiNum(pNtk) ); return pNtk->vCis->pArray[i]; } +static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { assert( i < Abc_NtkCoNum(pNtk) ); return pNtk->vCos->pArray[i]; } // 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 Vec_Fan_t * Abc_ObjFaninVec( Abc_Obj_t * pObj ) { return &pObj->vFanins; } +static inline Vec_Fan_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; } +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; } + +// working with complemented attributes of objects +static inline bool Abc_ObjIsComplement( Abc_Obj_t * p ) { return (bool)(((unsigned)p) & 01); } +static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned)(p) & ~01); } +static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned)(p) ^ 01); } +static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((unsigned)(p) ^ (c)); } // 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]++; } +static inline bool Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; } +static inline bool Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; } +static inline bool Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; } +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_ObjIsPio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_PO; } +static inline bool Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_LATCH; } +static inline bool Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_LATCH; } +static inline bool Abc_ObjIsCio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_LATCH; } // 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 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].iFan; } +static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].iFan; } +static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].iFan; } +static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i].iFan ]; } +static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0].iFan ]; } +static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i].iFan ]; } +static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0].iFan ]; } +static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1].iFan ]; } +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_ObjFaninC( Abc_Obj_t * pObj, int i ) { return pObj->vFanins.pArray[i].fCompl; } +static inline bool Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].fCompl; } +static inline bool Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].fCompl; } +static inline bool Abc_ObjFanoutC( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( !Abc_NtkIsLogic(pObj->pNtk) ); return (Abc_ObjFaninId0(pFanout) == (int)pObj->Id)? Abc_ObjFaninC0(pFanout) : Abc_ObjFaninC1(pFanout); } +static inline int Abc_ObjFaninL( Abc_Obj_t * pObj, int i ) { return pObj->vFanins.pArray[i].nLats; } +static inline int Abc_ObjFaninL0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].nLats; } +static inline int Abc_ObjFaninL1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].nLats; } +static inline int Abc_ObjFaninLMin( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MIN( Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) ); } +static inline int Abc_ObjFaninLMax( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MAX( Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) ); } 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; } +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_ObjFanoutFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( !Abc_NtkIsLogic(pObj->pNtk) ); return (Abc_ObjFaninId0(pFanout) == (int)pObj->Id)? Abc_ObjChild0(pFanout) : Abc_ObjChild1(pFanout); } +static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ pObj->vFanins.pArray[i].fCompl = 1; } +static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ pObj->vFanins.pArray[i].fCompl ^= 1; } +static inline void Abc_ObjSetFaninL( Abc_Obj_t * pObj, int i, int nLats ) { pObj->vFanins.pArray[i].nLats = nLats; } +static inline void Abc_ObjSetFaninL0( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[0].nLats = nLats; } +static inline void Abc_ObjSetFaninL1( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[1].nLats = nLats; } +static inline void Abc_ObjAddFaninL( Abc_Obj_t * pObj, int i, int nLats ) { pObj->vFanins.pArray[i].nLats += nLats; } +static inline void Abc_ObjAddFaninL0( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[0].nLats += nLats; } +static inline void Abc_ObjAddFaninL1( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[1].nLats += nLats; } +extern int Abc_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ); +extern void Abc_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ); +extern void Abc_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ); +extern int Abc_ObjFanoutLMin( Abc_Obj_t * pObj ); +extern int Abc_ObjFanoutLMax( Abc_Obj_t * pObj ); + +// checking the node type +static inline bool Abc_NodeIsAigAnd( Abc_Obj_t * pNode ) { assert(Abc_NtkHasAig(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; } +static inline bool Abc_NodeIsAigChoice( Abc_Obj_t * pNode ) { assert(Abc_NtkHasAig(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; } +static inline bool Abc_NodeIsConst( Abc_Obj_t * pNode ) { assert(Abc_ObjIsNode(Abc_ObjRegular(pNode))); return Abc_ObjFaninNum(Abc_ObjRegular(pNode)) == 0; } +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 ); // working with the traversal ID static inline void Abc_NodeSetTravId( Abc_Obj_t * pNode, int TravId ) { pNode->TravId = TravId; } @@ -415,29 +335,12 @@ static inline bool Abc_NodeIsTravIdCurrent( Abc_Obj_t * pNode ) { r 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 ); } +static inline void Abc_LatchSetInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)0; } +static inline void Abc_LatchSetInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)1; } +static inline void Abc_LatchSetInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)2; } +static inline bool Abc_LatchIsInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)0; } +static inline bool Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)1; } +static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)2; } // outputs the runtime in seconds #define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) @@ -447,59 +350,36 @@ static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_At //////////////////////////////////////////////////////////////////////// // 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 +#define Abc_NtkForEachObj( pNtk, pObj, i ) \ + for ( i = 0; i < Vec_PtrSize(pNtk->vObjs); i++ ) \ + if ( pObj = Abc_NtkObj(pNtk, i) ) +#define Abc_NtkForEachNet( pNtk, pNet, i ) \ + for ( i = 0; i < Vec_PtrSize(pNtk->vObjs); i++ ) \ + if ( (pNet = Abc_NtkObj(pNtk, i)) && Abc_ObjIsNet(pNet) ) +#define Abc_NtkForEachNode( pNtk, pNode, i ) \ + for ( i = 0; i < Vec_PtrSize(pNtk->vObjs); i++ ) \ + if ( (pNode = Abc_NtkObj(pNtk, i)) && Abc_ObjIsNode(pNode) ) +#define Abc_NtkForEachLatch( pNtk, pObj, i ) \ + for ( i = 0; i < Vec_PtrSize(pNtk->vLats); i++ ) \ + if ( pObj = Abc_NtkLatch(pNtk, i) ) // inputs and outputs -#define Abc_NtkForEachPi( pNtk, pPi, i ) \ +#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 ) \ +#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 ) \ +#define Abc_NtkForEachCi( pNtk, pCi, i ) \ + for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(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 ) \ +#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 ) \ +#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 ) \ +#define Abc_SopForEachCube( pSop, nFanins, pCube ) \ for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) -#define Abc_CubeForEachVar( pCube, Value, i ) \ +#define Abc_CubeForEachVar( pCube, Value, i ) \ for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) @@ -509,92 +389,57 @@ static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_At /*=== abcAig.c ==========================================================*/ extern Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk ); +extern Abc_Aig_t * Abc_AigDup( Abc_Aig_t * pMan, Abc_Aig_t * pManNew ); 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 int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_AigConst1( Abc_Aig_t * pMan ); +extern Abc_Obj_t * Abc_AigReset( Abc_Aig_t * pMan ); 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_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew ); 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 ); +extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate ); /*=== 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 ); +extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); /*=== abcCollapse.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ); +extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, 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_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj ); +extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj ); 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 int Abc_NtkGetLevelNum( 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_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes ); extern Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ); extern int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_NtkFraigRestore(); @@ -602,133 +447,95 @@ 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 char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, Vec_Str_t * vCube, int fMode ); +extern int Abc_NtkBddToSop( Abc_Ntk_t * pNtk ); +extern void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, 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 ); +/*=== abcMap.c ==========================================================*/ +extern int Abc_NtkUnmap( Abc_Ntk_t * pNtk ); /*=== 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_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); 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 int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); extern Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial ); +/*=== 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 void Abc_ObjAdd( Abc_Obj_t * pObj ); +extern Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ); +extern Abc_Obj_t * Abc_NtkDupConst1( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew ); +extern Abc_Obj_t * Abc_NtkDupReset( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew ); +extern void Abc_NtkDeleteObj( Abc_Obj_t * pObj ); +extern Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NodeCreateConst0( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NodeCreateConst1( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NodeCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); +extern Abc_Obj_t * Abc_NodeCreateBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); +extern Abc_Obj_t * Abc_NodeCreateAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern Abc_Obj_t * Abc_NodeCreateOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern Abc_Obj_t * Abc_NodeCreateMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ); +extern Abc_Obj_t * Abc_NodeClone( Abc_Obj_t * pNode ); /*=== abcNames.c ====================================================*/ +extern char * Abc_NtkRegisterName( Abc_Ntk_t * pNtk, char * pName ); +extern char * Abc_NtkRegisterNamePlus( Abc_Ntk_t * pNtk, char * pName, char * pSuffix ); 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 char * Abc_ObjNameUnique( Abc_Ntk_t * pNtk, char * pName ); +extern char * Abc_NtkLogicStoreName( Abc_Obj_t * pNodeNew, char * pNameOld ); +extern char * Abc_NtkLogicStoreNamePlus( Abc_Obj_t * pNodeNew, char * pNameOld, char * pSuffix ); +extern void Abc_NtkCreateCioNamesTable( Abc_Ntk_t * pNtk ); +extern void Abc_NtkDupCioNamesTable( 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 ); +extern Abc_Ntk_t * Abc_NtkNetlistToLogic( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkLogicToNetlistBench( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkAigToLogicSopBench( 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 ); +extern DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly ); +extern void Abc_NtkFreeGlobalBdds( 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_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func ); 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 void Abc_NtkFinalizeRegular( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern void Abc_NtkFinalizeLatches( Abc_Ntk_t * pNtk ); 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 Abc_Ntk_t * Abc_NtkSplitOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAllCis ); +extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); +extern Abc_Ntk_t * Abc_NtkSplitNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); 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 ); @@ -737,29 +544,12 @@ 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_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile ); 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 ); @@ -768,39 +558,37 @@ extern DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, Dd 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 ); +extern Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode ); +/*=== abcRenode.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple ); +extern DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ); /*=== 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 ); +extern bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose ); +extern solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk ); +/*=== abcSeq.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk ); +extern int Abc_NtkSeqLatchNum( Abc_Ntk_t * pNtk ); +extern void Abc_NtkSeqRetimeForward( Abc_Ntk_t * pNtk ); +extern void Abc_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk ); +extern void Abc_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk ); /*=== 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_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars ); 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 ); @@ -814,23 +602,17 @@ 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 ); +extern void Abc_SopWriteCnf( FILE * pFile, char * pClauses, Vec_Int_t * vVars ); +extern void Abc_SopAddCnfToSolver( solver * pSat, char * pClauses, Vec_Int_t * vVars, Vec_Int_t * vTemp ); /*=== 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 ); +extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup ); +extern Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode ); +extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); /*=== abcSweep.c ==========================================================*/ -extern int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); +extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, 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 ); +extern int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); /*=== abcTiming.c ==========================================================*/ extern Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ); extern Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ); @@ -847,73 +629,41 @@ 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_NtkStartReverseLevels( Abc_Ntk_t * pNtk ); 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 ); +extern void Abc_NodeSetReverseLevel( Abc_Obj_t * pObj, int LevelR ); +extern int Abc_NodeReadReverseLevel( Abc_Obj_t * pObj ); +extern int Abc_NodeReadRequiredLevel( Abc_Obj_t * pObj ); /*=== 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 /// //////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c index 16f66dc6..1d8931ec 100644 --- a/src/base/abc/abcAig.c +++ b/src/base/abc/abcAig.c @@ -30,8 +30,6 @@ - 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) @@ -50,22 +48,17 @@ 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 * pConst1; // the constant 1 node + Abc_Obj_t * pReset; // the sequential reset 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 * vStackDelete; // the nodes to be deleted 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 @@ -81,34 +74,24 @@ struct Abc_Aig_t_ 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)(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_AigReplace_int( Abc_Aig_t * pMan ); +static void Abc_AigDelete_int( Abc_Aig_t * pMan ); 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -133,21 +116,81 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) 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->vStackDelete = Vec_PtrAlloc( 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]--; + pMan->vLevels = Vec_VecAlloc( 100 ); + pMan->vLevelsR = Vec_VecAlloc( 100 ); // save the current network pMan->pNtkAig = pNtkAig; + // allocate constant nodes + pMan->pConst1 = Abc_NtkCreateNode( pNtkAig ); + pMan->pConst1->fPhase = 1; + pMan->pReset = Abc_NtkCreateNode( pNtkAig ); + // subtract these nodes from the total number + pNtkAig->nNodes -= 2; return pMan; } +/**Function************************************************************* + + Synopsis [Duplicated the AIG manager.] + + Description [Assumes that CI/CO nodes are already created. + Transfers the latch attributes on the edges.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Aig_t * Abc_AigDup( Abc_Aig_t * pMan, Abc_Aig_t * pManNew ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkCiNum(pMan->pNtkAig) == Abc_NtkCiNum(pManNew->pNtkAig) ); + assert( Abc_NtkCoNum(pMan->pNtkAig) == Abc_NtkCoNum(pManNew->pNtkAig) ); + assert( Abc_NtkLatchNum(pMan->pNtkAig) == Abc_NtkLatchNum(pManNew->pNtkAig) ); + // set mapping of the constant nodes + Abc_AigConst1( pMan )->pCopy = Abc_AigConst1( pManNew ); + Abc_AigReset( pMan )->pCopy = Abc_AigReset( pManNew ); + // set the mapping of CIs/COs + Abc_NtkForEachPi( pMan->pNtkAig, pObj, i ) + pObj->pCopy = Abc_NtkPi( pManNew->pNtkAig, i ); + Abc_NtkForEachPo( pMan->pNtkAig, pObj, i ) + pObj->pCopy = Abc_NtkPo( pManNew->pNtkAig, i ); + Abc_NtkForEachLatch( pMan->pNtkAig, pObj, i ) + pObj->pCopy = Abc_NtkLatch( pManNew->pNtkAig, i ); + // copy internal nodes + vNodes = Abc_AigDfs( pMan->pNtkAig, 1, 0 ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( !Abc_NodeIsAigAnd(pObj) ) + continue; + pObj->pCopy = Abc_AigAnd( pManNew, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // transfer latch attributes + Abc_ObjSetFaninL0( pObj->pCopy, Abc_ObjFaninL0(pObj) ); + Abc_ObjSetFaninL1( pObj->pCopy, Abc_ObjFaninL1(pObj) ); + } + // relink the choice nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( pObj->pData ) + pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; + Vec_PtrFree( vNodes ); + // relink the CO nodes + Abc_NtkForEachCo( pMan->pNtkAig, pObj, i ) + { + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + Abc_ObjSetFaninL0( pObj->pCopy, Abc_ObjFaninL0(pObj) ); + } + // get the number of nodes before and after + if ( Abc_NtkNodeNum(pMan->pNtkAig) != Abc_NtkNodeNum(pManNew->pNtkAig) ) + printf( "Warning: Structural hashing reduced %d nodes (should not happen).\n", + Abc_NtkNodeNum(pMan->pNtkAig) - Abc_NtkNodeNum(pManNew->pNtkAig) ); + return pManNew; +} + /**Function************************************************************* Synopsis [Deallocates the local AIG manager.] @@ -161,15 +204,13 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) ***********************************************************************/ void Abc_AigFree( Abc_Aig_t * pMan ) { + assert( Vec_PtrSize( pMan->vStackDelete ) == 0 ); 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->vStackDelete ); Vec_PtrFree( pMan->vStackReplaceOld ); Vec_PtrFree( pMan->vStackReplaceNew ); Vec_PtrFree( pMan->vNodes ); @@ -190,23 +231,18 @@ void Abc_AigFree( Abc_Aig_t * pMan ) ***********************************************************************/ 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; + int i, Counter; // collect the AND nodes that do not fanout - vDangles = Vec_PtrAlloc( 100 ); + assert( Vec_PtrSize( pMan->vStackDelete ) == 0 ); for ( i = 0; i < pMan->nBins; i++ ) Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) if ( Abc_ObjFanoutNum(pAnd) == 0 ) - Vec_PtrPush( vDangles, pAnd ); + Vec_PtrPush( pMan->vStackDelete, pAnd ); // process the dangling nodes and their MFFCs - Vec_PtrForEachEntry( vDangles, pAnd, i ) - Abc_AigDeleteNode( pMan, pAnd ); - Vec_PtrFree( vDangles ); - return nNodesOld - pMan->nEntries; + for ( Counter = 0; Vec_PtrSize(pMan->vStackDelete) > 0; Counter++ ) + Abc_AigDelete_int( pMan ); + return Counter; } /**Function************************************************************* @@ -229,7 +265,7 @@ bool Abc_AigCheck( Abc_Aig_t * pMan ) nFanins = Abc_ObjFaninNum(pObj); if ( nFanins == 0 ) { - if ( !Abc_AigNodeIsConst(pObj) ) + if ( pObj != pMan->pConst1 && pObj != pMan->pReset ) { printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" ); return 0; @@ -262,16 +298,6 @@ bool Abc_AigCheck( Abc_Aig_t * pMan ) 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; } @@ -286,7 +312,7 @@ bool Abc_AigCheck( Abc_Aig_t * pMan ) SeeAlso [] ***********************************************************************/ -int Abc_AigLevel( Abc_Ntk_t * pNtk ) +int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, LevelsMax; @@ -299,6 +325,39 @@ int Abc_AigLevel( Abc_Ntk_t * pNtk ) return LevelsMax; } +/**Function************************************************************* + + Synopsis [Read the constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigConst1( Abc_Aig_t * pMan ) +{ + return pMan->pConst1; +} + +/**Function************************************************************* + + Synopsis [Read the reset node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigReset( Abc_Aig_t * pMan ) +{ + return pMan->pReset; +} + + /**Function************************************************************* @@ -326,9 +385,9 @@ Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) 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); + 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]; @@ -337,13 +396,6 @@ Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) // 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; } @@ -376,17 +428,9 @@ Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * 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; } @@ -403,49 +447,25 @@ Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * ***********************************************************************/ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) { - Abc_Obj_t * pAnd, * pConst1; + Abc_Obj_t * pAnd; 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 ) + return Abc_ObjNot(pMan->pConst1); + if ( Abc_ObjRegular(p0) == pMan->pConst1 ) { - if ( p0 == pConst1 ) + if ( p0 == pMan->pConst1 ) return p1; - return Abc_ObjNot(pConst1); + return Abc_ObjNot(pMan->pConst1); } - if ( Abc_ObjRegular(p1) == pConst1 ) + if ( Abc_ObjRegular(p1) == pMan->pConst1 ) { - if ( p1 == pConst1 ) + if ( p1 == pMan->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; + return Abc_ObjNot(pMan->pConst1); } - // order the arguments if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) pAnd = p0, p0 = p1, p1 = pAnd; @@ -454,78 +474,7 @@ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) // 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; } @@ -542,15 +491,13 @@ Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, ***********************************************************************/ void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ) { - Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace; + Abc_Obj_t * pAnd, ** 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; @@ -614,77 +561,9 @@ clk = clock(); 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************************************************************* @@ -700,7 +579,7 @@ Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ) 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 )) ) + if ( pAnd = Abc_AigAndLookup( pMan, p0, p1 ) ) return pAnd; return Abc_AigAndCreate( pMan, p0, p1 ); } @@ -737,28 +616,7 @@ 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.] @@ -771,36 +629,12 @@ Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs ) ***********************************************************************/ 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) ); + pMiter = Abc_ObjNot(pMan->pConst1); for ( i = 0; i < vPairs->nSize; i += 2 ) { pXor = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] ); @@ -823,29 +657,17 @@ Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) SeeAlso [] ***********************************************************************/ -void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel ) +void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew ) { assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 ); assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 ); + assert( Vec_PtrSize(pMan->vStackDelete) == 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 ); - } + Abc_AigReplace_int( pMan ); + Abc_AigUpdateLevel_int( pMan ); + Abc_AigUpdateLevelR_int( pMan ); } /**Function************************************************************* @@ -859,10 +681,14 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool SeeAlso [] ***********************************************************************/ -void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) +void Abc_AigReplace_int( Abc_Aig_t * pMan ) { - Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout; - int k, v, iFanin; + Abc_Obj_t * pOld, * pNew, * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout; + int k, v, iFanin; + // get the pair of nodes to replace + assert( Vec_PtrSize(pMan->vStackReplaceOld) > 0 ); + pOld = Vec_PtrPop( pMan->vStackReplaceOld ); + pNew = Vec_PtrPop( pMan->vStackReplaceNew ); // make sure the old node is regular and has fanouts // (the new node can be complemented and can have fanouts) assert( !Abc_ObjIsComplement(pOld) ); @@ -877,7 +703,7 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, i continue; } // find the old node as a fanin of this fanout - iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id ); + iFanin = Vec_FanFindEntry( &pFanout->vFanins, pOld->Id ); assert( iFanin == 0 || iFanin == 1 ); // get the new fanin pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) ); @@ -886,7 +712,7 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, i 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 )) ) + 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 ); @@ -912,24 +738,18 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, i 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 ); - } - } + // 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 + assert( pFanout->fMarkB == 0 ); + pFanout->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanout), pFanout ); // the fanout has changed, update EXOR status of its fanouts Abc_ObjForEachFanout( pFanout, pFanoutFanout, v ) - if ( Abc_AigNodeIsAnd(pFanoutFanout) ) + if ( Abc_NodeIsAigAnd(pFanoutFanout) ) pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout); } // if the node has no fanouts left, remove its MFFC @@ -948,65 +768,88 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, i SeeAlso [] ***********************************************************************/ -void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) +void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld ) { - Abc_Obj_t * pNode0, * pNode1, * pTemp; - int i, k; + assert( Vec_PtrSize(pMan->vStackDelete) == 0 ); + Vec_PtrPush( pMan->vStackDelete, pOld ); + while ( Vec_PtrSize(pMan->vStackDelete) ) + Abc_AigDelete_int( pMan ); +} + +/**Function************************************************************* + + Synopsis [Performs internal deletion step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigDelete_int( Abc_Aig_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pRoot, * pObj; + int k; + // get the node to delete + assert( Vec_PtrSize(pMan->vStackDelete) > 0 ); + pRoot = Vec_PtrPop( pMan->vStackDelete ); // 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 ) + assert( !Abc_ObjIsComplement(pRoot) ); + assert( Abc_ObjIsNode(pRoot) ); + assert( Abc_ObjFaninNum(pRoot) == 2 ); + assert( Abc_ObjFanoutNum(pRoot) == 0 ); + + // collect the MFFC + vNodes = Abc_NodeMffcCollect( pRoot ); + + // if reverse levels are specified, schedule fanins of MFFC for updating + // currently, we do not do it because we do not know the correct level of the fanins + // also, it is unlikely that this will make a difference since we are + // processing the network forward while at this point fanins are left behind... +/* + if ( pObj->pNtk->vLevelsR ) + Vec_PtrForEachEntry( vNodes, pObj, k ) { - // remove the entry from the replacement array - for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ ) + Abc_Obj_t * pFanin; + if ( Abc_ObjIsCi(pObj) ) + continue; + pFanin = Abc_ObjFanin0(pObj); + if ( pFanin->fMarkB == 0 ) { - pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1]; - pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1]; + pFanin->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanin), pFanin ); + } + pFanin = Abc_ObjFanin1(pObj); + if ( pFanin->fMarkB == 0 ) + { + pFanin->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanin), pFanin ); } - 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 ) + // delete the nodes in MFFC + Vec_PtrForEachEntry( vNodes, pObj, k ) { - Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 ); - Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 ); + if ( Abc_ObjIsCi(pObj) ) + continue; + assert( Abc_ObjFanoutNum(pObj) == 0 ); + // remove the node from the table + Abc_AigAndDelete( pMan, pObj ); + // if the node is in the level structure, remove it + if ( pObj->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pObj ); + if ( pObj->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pObj ); + // remove the node from the network + Abc_NtkDeleteObj( pObj ); } - - // 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 ); + Vec_PtrFree( vNodes ); } - /**Function************************************************************* Synopsis [Updates the level of the node after it has changed.] @@ -1094,7 +937,7 @@ void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ) if ( pNode == NULL ) continue; assert( Abc_ObjIsNode(pNode) ); - assert( Abc_ObjReverseLevel(pNode) == i ); + assert( Abc_NodeReadReverseLevel(pNode) == i ); // clean the mark assert( pNode->fMarkB == 1 ); pNode->fMarkB = 0; @@ -1106,17 +949,17 @@ void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ) // get the new reverse level of this fanin LevelNew = 0; Abc_ObjForEachFanout( pFanin, pFanout, j ) - if ( LevelNew < Abc_ObjReverseLevel(pFanout) ) - LevelNew = Abc_ObjReverseLevel(pFanout); + if ( LevelNew < Abc_NodeReadReverseLevel(pFanout) ) + LevelNew = Abc_NodeReadReverseLevel(pFanout); LevelNew += 1; assert( LevelNew > i ); - if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change + if ( Abc_NodeReadReverseLevel(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 ); + Abc_NodeSetReverseLevel( pFanin, LevelNew ); // add the fanin to the data structure to update its fanins assert( pFanin->fMarkB == 0 ); pFanin->fMarkB = 1; @@ -1173,7 +1016,7 @@ void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) Abc_Obj_t * pTemp; int m; assert( pNode->fMarkB ); - vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) ); + vVecTemp = Vec_VecEntry( vStruct, Abc_NodeReadReverseLevel(pNode) ); Vec_PtrForEachEntry( vVecTemp, pTemp, m ) { if ( pTemp != pNode ) @@ -1206,7 +1049,7 @@ bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ) int i, iFanin; Abc_ObjForEachFanout( pNode, pFanout, i ) { - iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); + iFanin = Vec_FanFindEntry( &pFanout->vFanins, pNode->Id ); assert( iFanin >= 0 ); if ( Abc_ObjFaninC( pFanout, iFanin ) ) return 1; @@ -1235,7 +1078,7 @@ bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ) { if ( !Abc_NodeIsTravIdCurrent(pFanout) ) continue; - iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); + iFanin = Vec_FanFindEntry( &pFanout->vFanins, pNode->Id ); assert( iFanin >= 0 ); if ( Abc_ObjFaninC( pFanout, iFanin ) ) return 1; @@ -1263,7 +1106,7 @@ void Abc_AigPrintNode( Abc_Obj_t * pNode ) printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); return; } - if ( Abc_AigNodeIsConst(pNodeR) ) + if ( Abc_NodeIsConst(pNodeR) ) { printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" ); return; @@ -1294,7 +1137,7 @@ 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) ) + if ( !Abc_NodeIsAigAnd(pNode) ) return 1; pFanin0 = Abc_ObjFanin0(pNode); pFanin1 = Abc_ObjFanin1(pNode); @@ -1327,148 +1170,6 @@ bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ) 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 index 79b76348..1d23d7ed 100644 --- a/src/base/abc/abcCheck.c +++ b/src/base/abc/abcCheck.c @@ -20,12 +20,12 @@ #include "abc.h" #include "main.h" -//#include "seq.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +static bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ); static bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk ); static bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk ); static bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk ); @@ -38,10 +38,8 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -56,7 +54,7 @@ static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode( ***********************************************************************/ bool Abc_NtkCheck( Abc_Ntk_t * pNtk ) -{ +{ return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk ); } @@ -92,45 +90,25 @@ 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) ) + if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSeq(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) ) + if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) ) { fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" ); return 0; } if ( Abc_NtkHasMapping(pNtk) ) { - if ( pNtk->pManFunc != Abc_FrameReadLibGen() ) + if ( pNtk->pManFunc != Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) ) { 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; @@ -142,9 +120,6 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) 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 ) ) @@ -173,8 +148,11 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) } // check the nodes - if ( Abc_NtkIsStrash(pNtk) ) - Abc_AigCheck( pNtk->pManFunc ); + if ( Abc_NtkHasAig(pNtk) ) + { + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigCheck( pNtk->pManFunc ); + } else { Abc_NtkForEachNode( pNtk, pNode, i ) @@ -189,7 +167,7 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) // finally, check for combinational loops // clk = clock(); - if ( !Abc_NtkIsAcyclic( pNtk ) ) + if ( !Abc_NtkIsSeq( pNtk ) && !Abc_NtkIsAcyclic( pNtk ) ) { fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" ); return 0; @@ -198,29 +176,14 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) // 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; - } + { +// if ( pNtk->Type != pNtk->pExdc->Type ) +// { +// fprintf( stdout, "NetworkCheck: Network and its EXDC have different types.\n" ); +// return 0; +// } + return Abc_NtkCheck( pNtk->pExdc ); } -*/ return 1; } @@ -237,61 +200,73 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) ***********************************************************************/ bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk ) { - Abc_Obj_t * pObj; - Vec_Int_t * vNameIds; + stmm_generator * gen; + Abc_Obj_t * pNet, * pNet2, * pObj; char * pName; - int i, NameId; + int i; if ( Abc_NtkIsNetlist(pNtk) ) - return 1; + { + // check that the nets in the table are also in the network + stmm_foreach_item( pNtk->tName2Net, gen, &pName, (char**)&pNet ) + { + if ( pNet->pData != pName ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" has different name compared to the one in the name table.\n", pNet->pData ); + return 0; + } + } + // check that the nets with names are also in the table + Abc_NtkForEachNet( pNtk, pNet, i ) + { + if ( pNet->pData && !stmm_lookup( pNtk->tName2Net, pNet->pData, (char**)&pNet2 ) ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" is in the network but not in the name table.\n", pNet->pData ); + return 0; + } + } + } - // check that each CI/CO has a name - Abc_NtkForEachCi( pNtk, pObj, i ) + // check PI/PO/latch names + Abc_NtkForEachPi( pNtk, pObj, i ) { - pObj = Abc_ObjFanout0Ntk(pObj); - if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) + if ( !stmm_lookup( pNtk->tObj2Name, (char *)pObj, &pName ) ) + { + fprintf( stdout, "NetworkCheck: PI \"%s\" is in the network but not in the name table.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_NtkIsNetlist(pNtk) && strcmp( Abc_ObjName(Abc_ObjFanout0(pObj)), pName ) ) { - fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id ); + fprintf( stdout, "NetworkCheck: PI \"%s\" has a different name compared to its net.\n", Abc_ObjName(pObj) ); return 0; } } - Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_NtkForEachPo( pNtk, pObj, i ) { - pObj = Abc_ObjFanin0Ntk(pObj); - if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) + if ( !stmm_lookup( pNtk->tObj2Name, (char *)pObj, &pName ) ) + { + fprintf( stdout, "NetworkCheck: PO \"%s\" is in the network but not in the name table.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_NtkIsNetlist(pNtk) && strcmp( Abc_ObjName(Abc_ObjFanin0(pObj)), pName ) ) { - fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id ); + fprintf( stdout, "NetworkCheck: PO \"%s\" has a different name compared to its net.\n", Abc_ObjName(pObj) ); 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 ) + Abc_NtkForEachLatch( pNtk, pObj, i ) { - if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL ) + if ( !stmm_lookup( pNtk->tObj2Name, (char *)pObj, &pName ) ) { - 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 ); + fprintf( stdout, "NetworkCheck: Latch \"%s\" is in the network but not in the name table.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_NtkIsNetlist(pNtk) && strcmp( Abc_ObjName(Abc_ObjFanout0(pObj)), pName ) ) + { + fprintf( stdout, "NetworkCheck: Latch \"%s\" has a different name compared to its net.\n", Abc_ObjName(pObj) ); 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; } @@ -312,6 +287,12 @@ bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk ) Abc_Obj_t * pObj; int i; + if ( Abc_NtkCiNum(pNtk) != Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Incorrect size of the PI array.\n" ); + return 0; + } + // check that PIs are indeed PIs Abc_NtkForEachPi( pNtk, pObj, i ) { @@ -360,6 +341,12 @@ bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk ) Abc_Obj_t * pObj; int i; + if ( Abc_NtkCoNum(pNtk) != Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Incorrect size of the PO array.\n" ); + return 0; + } + // check that POs are indeed POs Abc_NtkForEachPo( pNtk, pObj, i ) { @@ -427,14 +414,10 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) 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 ) + if ( Vec_FanFindEntry( &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) ); @@ -444,7 +427,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) // 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 ) + if ( Vec_FanFindEntry( &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) ); @@ -452,10 +435,13 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) } } + if ( !Abc_FrameIsFlagEnabled("checkfio") ) + return Value; + // 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] ) + if ( pObj->vFanins.pArray[k].iFan == pObj->vFanins.pArray[i].iFan ) { printf( "Warning: Node %s has", Abc_ObjName(pObj) ); printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) ); @@ -468,7 +454,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) // 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] ) + if ( pObj->vFanouts.pArray[k].iFan == pObj->vFanouts.pArray[i].iFan ) { printf( "Warning: Node %s has", Abc_ObjName(pObj) ); printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) ); @@ -525,7 +511,7 @@ bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) // 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) ); + fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjName(pNode) ); return 0; } // the netlist and SOP logic network should have SOPs @@ -533,7 +519,7 @@ bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) { if ( !Abc_SopCheck( pNode->pData, Abc_ObjFaninNum(pNode) ) ) { - fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) ); + fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjName(pNode) ); return 0; } } @@ -542,11 +528,11 @@ bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) 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) ); + fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjName(pNode) ); return 0; } } - else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) ) + else if ( !Abc_NtkHasMapping(pNtk) ) { assert( 0 ); } @@ -567,14 +553,19 @@ bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ) { int Value = 1; + if ( pNtk->vLats->nSize != Abc_NtkLatchNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Incorrect size of the latch array.\n" ); + return 0; + } // 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) ); + fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but has not latch label.\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 ) + if ( (int)pLatch->pData < 0 || (int)pLatch->pData > 2 ) { fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n", Abc_ObjName(pLatch), (int)pLatch->pData ); @@ -586,33 +577,6 @@ bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ) 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; } @@ -696,26 +660,24 @@ bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) SeeAlso [] ***********************************************************************/ -bool Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +bool Abc_NtkCompareLatches( 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) ) + if ( Abc_NtkLatchNum(pNtk1) != Abc_NtkLatchNum(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 ) + Abc_NtkForEachLatch( pNtk1, pObj1, i ) { - if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 ) + if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkLatch(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))) ); + printf( "Latch #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkLatch(pNtk2,i)) ); return 0; } } @@ -733,207 +695,19 @@ bool Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) SeeAlso [] ***********************************************************************/ -bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ) +bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) { Abc_NtkOrderObjsByName( pNtk1, fComb ); Abc_NtkOrderObjsByName( pNtk2, fComb ); + if ( !Abc_NtkCompareLatches( pNtk1, pNtk2, fComb ) ) + return 0; 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; - } + 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( 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, * pFanin; - 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) ) ); - pFanin = Abc_ObjFanin0(pObj); - if ( pFanin != pObjCi ) - { - printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly. The name of the CO fanin is %s.\n", - Abc_ObjName(pObj), Abc_ObjName(Abc_ObjFanin0(pObj)) ); - fRetValue = 0; - } - } - return fRetValue; -} - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c index af23f18a..2fbbee37 100644 --- a/src/base/abc/abcDfs.c +++ b/src/base/abc/abcDfs.c @@ -24,45 +24,17 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +static void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +static void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +static void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +static void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ); +static int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode ); +static bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ); + //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// -/**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.] @@ -132,7 +104,6 @@ Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes return vNodes; } - /**Function************************************************************* Synopsis [Performs DFS for one node.] @@ -144,9 +115,9 @@ Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes SeeAlso [] ***********************************************************************/ -void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { - Abc_Obj_t * pFanout; + Abc_Obj_t * pFanin; int i; assert( !Abc_ObjIsNet(pNode) ); // if this node is already visited, skip @@ -155,17 +126,17 @@ void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // skip the CI - if ( Abc_ObjIsCo(pNode) ) + if ( Abc_ObjIsCi(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 ); + Abc_ObjForEachFanin( pNode, pFanin, 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 reverse DFS ordered array of logic nodes.] @@ -195,10 +166,9 @@ Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ) 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 ); + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_NodeIsConst(pObj) ) + Vec_PtrPush( vNodes, pObj ); return vNodes; } @@ -213,7 +183,7 @@ Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanout; int i; @@ -230,19 +200,17 @@ void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) // visit the transitive fanin of the node pNode = Abc_ObjFanout0Ntk(pNode); Abc_ObjForEachFanout( pNode, pFanout, i ) - Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); + Abc_NtkDfsReverse_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 ); + Vec_PtrPush( vNodes, pNode ); } + /**Function************************************************************* - Synopsis [Returns the levelized array of TFO nodes.] + Synopsis [Returns the DFS ordered array of logic nodes.] - Description [Collects the levelized array of internal nodes, leaving out CIs/COs. + Description [Collects only the internal nodes, leaving out CIs/COs. However it marks both CIs and COs with the current TravId.] SideEffects [] @@ -250,102 +218,34 @@ void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ) { Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pFanout; - int i, k; + Abc_Obj_t * pNode; + int i; 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++ ) + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + Abc_NtkForEachCo( pNtk, pNode, 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 ); + Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); + Abc_NodeSetTravIdCurrent( pNode ); + if ( fCollectCos ) + Vec_PtrPush( vNodes, pNode ); } - // iterate through the levels - for ( i = 0; i <= nLevels; i++ ) + // collect dangling nodes if asked to + if ( fCollectAll ) { - // 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; - } - } + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_NodeIsTravIdCurrent(pNode) ) + Abc_AigDfs_rec( pNode, vNodes ); } return vNodes; } - /**Function************************************************************* Synopsis [Performs DFS for one node.] @@ -357,7 +257,7 @@ Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNo SeeAlso [] ***********************************************************************/ -void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; @@ -366,55 +266,66 @@ void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); + // skip the PI + if ( Abc_ObjIsCi(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); // visit the transitive fanin of the node Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NtkDfsSeq_rec( pFanin, vNodes ); + Abc_AigDfs_rec( pFanin, vNodes ); + // visit the equivalent nodes + if ( Abc_NodeIsAigChoice( 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 array of nodes and latches reachable from POs.] + Synopsis [Collects nodes in the DFS manner by level.] - Description [] + Description [The number of levels should be set!!!] SideEffects [] SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ) +Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi ) { - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; + Vec_Vec_t * vLevels; + Abc_Obj_t * pFanout; int i; - assert( !Abc_NtkIsNetlist(pNtk) ); + assert( fTfi == 0 ); + assert( !Abc_NtkIsNetlist(pNode->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; + 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 [Performs DFS for one node.] + Synopsis [Collects nodes in the DFS manner by level.] - Description [] + Description [The number of levels should be set!!!] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ) { Abc_Obj_t * pFanout; int i; @@ -423,16 +334,21 @@ void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); - // visit the transitive fanin of the node + // 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_NtkDfsSeqReverse_rec( pFanout, vNodes ); - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pNode ); + Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); } + /**Function************************************************************* - Synopsis [Returns the array of nodes and latches reachable from POs.] + Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [] @@ -441,28 +357,26 @@ void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ) +int Abc_NtkGetLevelNum( Abc_Ntk_t * pNtk ) { - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i; - assert( !Abc_NtkIsNetlist(pNtk) ); - // set the traversal ID + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the traversal ID for this traversal 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; + // perform the traversal + LevelsMax = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkGetLevelNum_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + return LevelsMax; } - /**Function************************************************************* - Synopsis [Iterative version of the DFS procedure.] + Synopsis [Recursively counts the number of logic levels of one node.] Description [] @@ -471,94 +385,81 @@ Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes ) +int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode ) { - Abc_Obj_t * pNode, * pFanin; - int iFanin; - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pRoot ) ) - return; + Abc_Obj_t * pFanin; + int i, Level; + assert( !Abc_ObjIsNet(pNode) ); + // skip the PI + if ( Abc_ObjIsCi(pNode) ) + return 0; + 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( 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 ) + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + pNode->Level = 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) { - // 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 ); + Level = Abc_NtkGetLevelNum_rec( Abc_ObjFanin0Ntk(pFanin) ); + if ( pNode->Level < (unsigned)Level ) + pNode->Level = Level; } + pNode->Level++; + return pNode->Level; } + /**Function************************************************************* - Synopsis [Returns the DFS ordered array of logic nodes.] + Synopsis [Detects combinational loops.] - Description [Collects only the internal nodes, leaving CIs and CO. - However it marks with the current TravId both CIs and COs.] + 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 [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ) +bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ) { - 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_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 ) { - Abc_NtkForEachNode( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - Abc_NtkDfs_iter( vStack, pObj, vNodes ); + 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, " (cone of CO \"%s\")\n", Abc_ObjName(pNode) ); + break; } - Vec_PtrFree( vStack ); - return vNodes; + return fAcyclic; } - /**Function************************************************************* - Synopsis [Performs DFS for one node.] + Synopsis [Recursively detects combinational loops.] Description [] @@ -567,492 +468,23 @@ Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ) SeeAlso [] ***********************************************************************/ -void Abc_NtkDfsHie_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) +bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ) { - 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 ) || pNode->Type == ABC_OBJ_CONST1); - // 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 ) || pNode->Type == ABC_OBJ_CONST1); - // 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_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)) ) + if ( Abc_ObjIsCi(pNode) ) return 1; - assert( Abc_ObjIsNode(pNode) ); + 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) ); + fprintf( stdout, "Network \"%s\" contains combinational loop!\n", pNtk->pName ); + fprintf( stdout, "Node \"%s\" is encountered twice on the following path:\n", Abc_ObjName(pNode) ); + fprintf( stdout, " %s", Abc_ObjName(pNode) ); return 0; } // mark this node as a node on the current path @@ -1070,193 +502,14 @@ bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ) if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) ) continue; // return as soon as the loop is detected - fprintf( stdout, " %s ->", Abc_ObjName(pFanin) ); + fprintf( stdout, " <-- %s", Abc_ObjName(pNode) ); 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 index c8536695..2bc87c85 100644 --- a/src/base/abc/abcFanio.c +++ b/src/base/abc/abcFanio.c @@ -24,49 +24,12 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#define ABC_LARGE_ID ((1<<24)-1) // should correspond to value in "vecFan.h" + //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// -/**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.] @@ -84,16 +47,12 @@ void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * 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 ); + assert( pObj->Id < ABC_LARGE_ID ); // created but forgot to add it to the network? + assert( pFaninR->Id < ABC_LARGE_ID ); // created but forgot to add it to the network? + Vec_FanPush( pObj->pNtk->pMmStep, &pObj->vFanins, Vec_Int2Fan(pFaninR->Id) ); + Vec_FanPush( pObj->pNtk->pMmStep, &pFaninR->vFanouts, Vec_Int2Fan(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) ); } @@ -114,12 +73,14 @@ void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) assert( !Abc_ObjIsComplement(pFanin) ); assert( pObj->pNtk == pFanin->pNtk ); assert( pObj->Id >= 0 && pFanin->Id >= 0 ); - if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) ) + assert( pObj->Id < ABC_LARGE_ID ); // created but forgot to add it to the network? + assert( pFanin->Id < ABC_LARGE_ID ); // created but forgot to add it to the network? + if ( !Vec_FanDeleteEntry( &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 ) ) + if ( !Vec_FanDeleteEntry( &pFanin->vFanouts, pObj->Id ) ) { printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id ); return; @@ -140,19 +101,16 @@ void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) ***********************************************************************/ void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ) { - Vec_Int_t * vFaninsOld; + Vec_Fan_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] ); + pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k].iFan ); Abc_ObjDeleteFanin( pObj, pFanin ); } - pObj->fCompl0 = 0; - pObj->fCompl1 = 0; - assert( vFaninsOld->nSize == 0 ); } /**Function************************************************************* @@ -172,7 +130,7 @@ void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ) 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; + int iFanin, fCompl, nLats; assert( !Abc_ObjIsComplement(pObj) ); assert( !Abc_ObjIsComplement(pFaninOld) ); assert( pFaninOld != pFaninNewR ); @@ -180,74 +138,30 @@ void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFa // assert( pObj != pFaninNewR ); assert( pObj->pNtk == pFaninOld->pNtk ); assert( pObj->pNtk == pFaninNewR->pNtk ); - if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 ) + if ( (iFanin = Vec_FanFindEntry( &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); + fCompl = Abc_ObjFaninC(pObj, iFanin); + nLats = Abc_ObjFaninL(pObj, iFanin); // replace the old fanin entry by the new fanin entry (removes attributes) - Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id ); + Vec_FanWriteEntry( &pObj->vFanins, iFanin, Vec_Int2Fan(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 ); + if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) ) + Abc_ObjSetFaninC( pObj, iFanin ); + if ( nLats ) + Abc_ObjSetFaninL( pObj, iFanin, nLats ); // update the fanout of the fanin - if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) ) + if ( !Vec_FanDeleteEntry( &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; + Vec_FanPush( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, Vec_Int2Fan(pObj->Id) ); } /**Function************************************************************* @@ -263,24 +177,23 @@ Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc ***********************************************************************/ void Abc_ObjTransferFanout( Abc_Obj_t * pNodeFrom, Abc_Obj_t * pNodeTo ) { - Vec_Ptr_t * vFanouts; + Vec_Ptr_t * vFanouts = pNodeFrom->pNtk->vPtrTemp; int nFanoutsOld, i; assert( !Abc_ObjIsComplement(pNodeFrom) ); assert( !Abc_ObjIsComplement(pNodeTo) ); - assert( !Abc_ObjIsPo(pNodeFrom) && !Abc_ObjIsPo(pNodeTo) ); + assert( Abc_ObjIsNode(pNodeFrom) ); + assert( Abc_ObjIsNode(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************************************************************* @@ -298,34 +211,16 @@ void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) { assert( !Abc_ObjIsComplement(pNodeOld) ); assert( !Abc_ObjIsComplement(pNodeNew) ); + assert( Abc_ObjIsNode(pNodeOld) ); + assert( Abc_ObjIsNode(pNodeNew) ); assert( pNodeOld->pNtk == pNodeNew->pNtk ); assert( pNodeOld != pNodeNew ); assert( Abc_ObjFanoutNum(pNodeOld) > 0 ); + assert( Abc_ObjFanoutNum(pNodeNew) == 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; + Abc_NtkDeleteObj( pNodeOld ); } diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index f3297d8f..e5af1829 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -19,21 +19,15 @@ ***********************************************************************/ #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 ); +static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -52,8 +46,8 @@ int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) Abc_Obj_t * pNode; DdManager * dd; int nFaninsMax, i; - - assert( Abc_NtkHasSop(pNtk) ); + + assert( Abc_NtkIsSopLogic(pNtk) ); // start the functionality manager nFaninsMax = Abc_NtkGetFaninMax( pNtk ); @@ -75,7 +69,7 @@ int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) Cudd_Ref( pNode->pData ); } - Extra_MmFlexStop( pNtk->pManFunc ); + Extra_MmFlexStop( pNtk->pManFunc, 0 ); pNtk->pManFunc = dd; // update the network type @@ -99,40 +93,27 @@ 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); + // check the logic function of the node 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 + Abc_SopForEachCube( pSop, nVars, pCube ) { - // check the logic function of the node - Abc_SopForEachCube( pSop, nVars, pCube ) + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + Abc_CubeForEachVar( pCube, Value, v ) { - 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 ); + 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 ); - Cudd_RecursiveDeref( dd, bCube ); } + 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) ); @@ -159,7 +140,7 @@ void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) Abc_Obj_t * pNode; int nFaninsMax, fFound, i; - assert( Abc_NtkHasSop(pNtk) ); + assert( Abc_NtkIsSopLogic(pNtk) ); // check if there are nodes with complemented SOPs fFound = 0; @@ -184,7 +165,7 @@ void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) 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 ); + pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), vCube, 1 ); Cudd_RecursiveDeref( dd, bFunc ); assert( !Abc_SopIsComplement(pNode->pData) ); } @@ -200,32 +181,27 @@ void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) Synopsis [Converts the network from BDD to SOP representation.] - Description [If the flag is set to 1, forces the direct phase of all covers.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; - Extra_MmFlex_t * pManNew; DdManager * dd = pNtk->pManFunc; DdNode * bFunc; + int RetValue, i; Vec_Str_t * vCube; - int i, fMode; - - if ( fDirect ) - fMode = 1; - else - fMode = -1; - assert( Abc_NtkHasBdd(pNtk) ); - if ( dd->size > 0 ) + assert( Abc_NtkIsBddLogic(pNtk) ); Cudd_zddVarsFromBddVars( dd, 2 ); - // create the new manager - pManNew = Extra_MmFlexStart(); + // allocate the new manager + pNtk->pManFunc = Extra_MmFlexStart(); + // update the network type + pNtk->ntkFunc = ABC_FUNC_SOP; // go through the objects vCube = Vec_StrAlloc( 100 ); @@ -233,32 +209,19 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) { 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 ); + pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), vCube, -1 ); + if ( pNode->pData == NULL ) return 0; - } + Cudd_RecursiveDeref( dd, bFunc ); } 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 ); + RetValue = Cudd_CheckZeroRef( dd ); + if ( RetValue > 0 ) + printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); +// Cudd_PrintInfo( dd, stdout ); + Cudd_Quit( dd ); return 1; } @@ -273,7 +236,7 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) SeeAlso [] ***********************************************************************/ -char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ) +char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, Vec_Str_t * vCube, int fMode ) { int fVerify = 0; char * pSop; @@ -283,25 +246,22 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun 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 ); + if ( bFuncOn == Cudd_ReadLogicZero(dd) ) + sprintf( pSop, "%s 0\n", vCube->pArray ); else - sprintf( pSop, "%s %d\n", vCube->pArray, !fMode ); + sprintf( pSop, "%s 1\n", vCube->pArray ); 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 ); @@ -336,36 +296,20 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun 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 ); - } + 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 ); - } + bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover ); + Cudd_Ref( zCover ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); nCubes = Abc_CountZddCubes( dd, zCover ); fPhase = 1; } @@ -374,13 +318,6 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun 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 ); @@ -479,11 +416,11 @@ int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFani SeeAlso [] ***********************************************************************/ -void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) +void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, 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 ); + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + *ppSop0 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), vCube, 0 ); + *ppSop1 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), vCube, 1 ); } @@ -510,8 +447,6 @@ void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes ) (*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 ); @@ -537,616 +472,6 @@ int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ) } -/**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 index 0e35e774..1a1ab75f 100644 --- a/src/base/abc/abcInt.h +++ b/src/base/abc/abcInt.h @@ -29,24 +29,18 @@ /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// -#define ABC_NUM_STEPS 10 - //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// +/// END OF FILE /// //////////////////////////////////////////////////////////////////////// #endif -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/abc/abcLatch.c b/src/base/abc/abcLatch.c index d96bbfac..d804601e 100644 --- a/src/base/abc/abcLatch.c +++ b/src/base/abc/abcLatch.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -45,10 +45,10 @@ bool Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot ) assert( Abc_ObjIsLatch(pLatch) ); if ( pLatch == pLatchRoot ) return 1; - pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); - if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) + pFanin = Abc_ObjFanin0(pLatch); + if ( !Abc_ObjIsLatch(pFanin) ) return 0; - return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); + return Abc_NtkLatchIsSelfFeed_rec( pFanin, pLatch ); } /**Function************************************************************* @@ -66,10 +66,10 @@ 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)) ) + pFanin = Abc_ObjFanin0(pLatch); + if ( !Abc_ObjIsLatch(pFanin) ) return 0; - return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); + return Abc_NtkLatchIsSelfFeed_rec( pFanin, pLatch ); } /**Function************************************************************* @@ -89,234 +89,10 @@ int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ) 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 ); -} //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcLib.c b/src/base/abc/abcLib.c deleted file mode 100644 index feff1478..00000000 --- a/src/base/abc/abcLib.c +++ /dev/null @@ -1,454 +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 ) - { - 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 index e1c0f4fd..e143ba7b 100644 --- a/src/base/abc/abcMinBase.c +++ b/src/base/abc/abcMinBase.c @@ -27,7 +27,7 @@ static int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -65,8 +65,8 @@ int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) ***********************************************************************/ int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) { - Vec_Str_t * vSupport; - Vec_Ptr_t * vFanins; + Vec_Str_t * vSupport = pNode->pNtk->vStrTemp; + Vec_Ptr_t * vFanins = pNode->pNtk->vPtrTemp; DdNode * bTemp; int i, nVars; @@ -74,16 +74,11 @@ int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) 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 ) @@ -93,8 +88,6 @@ int Abc_NodeMinimumBase( Abc_Obj_t * 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; } @@ -112,11 +105,12 @@ int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; - int i, Counter; + int i, Counter, fChanged; assert( Abc_NtkIsBddLogic(pNtk) ); Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) - Counter += Abc_NodeRemoveDupFanins( pNode ); + while ( fChanged = Abc_NodeRemoveDupFanins(pNode) ) + Counter += fChanged; return Counter; } @@ -131,7 +125,7 @@ int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode ) +int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin1, * pFanin2; int i, k; @@ -162,24 +156,6 @@ int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode ) 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.] @@ -249,256 +225,6 @@ int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ) return Counter; } - - -/**Function************************************************************* - - Synopsis [Find the number of unique variables after collapsing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCheckDupFanin( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, int * piFanin ) -{ - Abc_Obj_t * pObj; - int i, Counter = 0; - Abc_ObjForEachFanin( pFanout, pObj, i ) - if ( pObj == pFanin ) - { - if ( piFanin ) - *piFanin = i; - Counter++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Find the number of unique variables after collapsing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCollapseSuppSize( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins ) -{ - Abc_Obj_t * pObj; - int i; - Vec_PtrClear( vFanins ); - Abc_ObjForEachFanin( pFanout, pObj, i ) - if ( pObj != pFanin ) - Vec_PtrPushUnique( vFanins, pObj ); - Abc_ObjForEachFanin( pFanin, pObj, i ) - Vec_PtrPushUnique( vFanins, pObj ); - return Vec_PtrSize( vFanins ); -} - -/**Function************************************************************* - - Synopsis [Returns the index of the new fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjFaninNumberNew( Vec_Ptr_t * vFanins, Abc_Obj_t * pFanin ) -{ - Abc_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( vFanins, pObj, i ) - if ( pObj == pFanin ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Find the permutation map for the given node into the new order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCollapsePermMap( Abc_Obj_t * pNode, Abc_Obj_t * pSkip, Vec_Ptr_t * vFanins, int * pPerm ) -{ - Abc_Obj_t * pFanin; - int i; - for ( i = 0; i < Vec_PtrSize(vFanins); i++ ) - pPerm[i] = i; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( pFanin == pSkip ) - continue; - pPerm[i] = Abc_ObjFaninNumberNew( vFanins, pFanin ); - if ( pPerm[i] == -1 ) - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Computes support of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NodeCollapseFunc( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) -{ - DdManager * dd = pFanin->pNtk->pManFunc; - DdNode * bVar, * bFunc0, * bFunc1, * bTemp, * bFanin, * bFanout; - int RetValue, nSize, iFanin; - // can only eliminate if fanin occurs in the fanin list of the fanout exactly once - if ( Abc_NodeCheckDupFanin( pFanin, pFanout, &iFanin ) != 1 ) - return NULL; - // find the new number of fanins after collapsing - nSize = Abc_NodeCollapseSuppSize( pFanin, pFanout, vFanins ); - bVar = Cudd_bddIthVar( dd, nSize - 1 ); - assert( nSize <= dd->size ); - // find the permutation after collapsing - RetValue = Abc_NodeCollapsePermMap( pFanin, NULL, vFanins, pPermFanin ); - assert( RetValue ); - RetValue = Abc_NodeCollapsePermMap( pFanout, pFanin, vFanins, pPermFanout ); - assert( RetValue ); - // cofactor the local function of the node - bVar = Cudd_bddIthVar( dd, iFanin ); - bFunc0 = Cudd_Cofactor( dd, pFanout->pData, Cudd_Not(bVar) ); Cudd_Ref( bFunc0 ); - bFunc1 = Cudd_Cofactor( dd, pFanout->pData, bVar ); Cudd_Ref( bFunc1 ); - // find the permutation after collapsing - bFunc0 = Cudd_bddPermute( dd, bTemp = bFunc0, pPermFanout ); Cudd_Ref( bFunc0 ); - Cudd_RecursiveDeref( dd, bTemp ); - bFunc1 = Cudd_bddPermute( dd, bTemp = bFunc1, pPermFanout ); Cudd_Ref( bFunc1 ); - Cudd_RecursiveDeref( dd, bTemp ); - bFanin = Cudd_bddPermute( dd, pFanin->pData, pPermFanin ); Cudd_Ref( bFanin ); - // create the new function - bFanout = Cudd_bddIte( dd, bFanin, bFunc1, bFunc0 ); Cudd_Ref( bFanout ); - Cudd_RecursiveDeref( dd, bFanin ); - Cudd_RecursiveDeref( dd, bFunc1 ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_Deref( bFanout ); - return bFanout; -} - -/**Function************************************************************* - - Synopsis [Collapses one node into its fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCollapse( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) -{ - Abc_Obj_t * pFanoutNew, * pObj; - DdNode * bFanoutNew; - int i; - assert( Abc_NtkIsBddLogic(pFanin->pNtk) ); - assert( Abc_ObjIsNode(pFanin) ); - assert( Abc_ObjIsNode(pFanout) ); - bFanoutNew = Abc_NodeCollapseFunc( pFanin, pFanout, vFanins, pPermFanin, pPermFanout ); - if ( bFanoutNew == NULL ) - return 0; - Cudd_Ref( bFanoutNew ); - // create the new node - pFanoutNew = Abc_NtkCreateNode( pFanin->pNtk ); - Vec_PtrForEachEntry( vFanins, pObj, i ) - Abc_ObjAddFanin( pFanoutNew, pObj ); - pFanoutNew->pData = bFanoutNew; - // minimize the node - Abc_NodeMinimumBase( pFanoutNew ); - // transfer the fanout - Abc_ObjTransferFanout( pFanout, pFanoutNew ); - assert( Abc_ObjFanoutNum( pFanout ) == 0 ); - Abc_NtkDeleteObj_rec( pFanout, 1 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Eliminates the nodes into their fanouts if the node size does not exceed this number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose ) -{ - extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); - Vec_Ptr_t * vFanouts, * vFanins, * vNodes; - Abc_Obj_t * pNode, * pFanout; - int * pPermFanin, * pPermFanout; - int RetValue, i, k; - assert( nMaxSize > 0 ); - assert( Abc_NtkIsLogic(pNtk) ); - // convert network to BDD representation - if ( !Abc_NtkToBdd(pNtk) ) - { - fprintf( stdout, "Converting to BDD has failed.\n" ); - return 0; - } - // prepare nodes for sweeping - Abc_NtkRemoveDupFanins( pNtk ); - Abc_NtkMinimumBase( pNtk ); - Abc_NtkCleanup( pNtk, 0 ); - // get the nodes in the given order - vNodes = fReverse? Abc_NtkDfsReverse( pNtk ) : Abc_NtkDfs( pNtk, 0 ); - // go through the nodes and decide is they can be eliminated - pPermFanin = ALLOC( int, nMaxSize + 100 ); - pPermFanout = ALLOC( int, nMaxSize + 100 ); - vFanins = Vec_PtrAlloc( 100 ); - vFanouts = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_NodeFindCoFanout(pNode) != NULL ) - continue; - if ( Abc_ObjFaninNum(pNode) > nMaxSize ) - continue; - Abc_ObjForEachFanout( pNode, pFanout, k ) - if ( Abc_NodeCollapseSuppSize(pNode, pFanout, vFanins) > nMaxSize ) - break; - if ( k < Abc_ObjFanoutNum(pNode) ) - continue; - // perform elimination - Abc_NodeCollectFanouts( pNode, vFanouts ); - Vec_PtrForEachEntry( vFanouts, pFanout, k ) - { - RetValue = Abc_NodeCollapse( pNode, pFanout, vFanins, pPermFanin, pPermFanout ); - assert( RetValue ); - } - } - Abc_NtkBddReorder( pNtk, 0 ); - Vec_PtrFree( vFanins ); - Vec_PtrFree( vFanouts ); - Vec_PtrFree( vNodes ); - free( pPermFanin ); - free( pPermFanout ); - return 1; -} - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcNames.c b/src/base/abc/abcNames.c index 91964dfa..2bf6461b 100644 --- a/src/base/abc/abcNames.c +++ b/src/base/abc/abcNames.c @@ -25,47 +25,95 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Returns the unique name for the object.] + Synopsis [Registers the name with the string memory manager.] - 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!] + Description [This function should be used to register all names + permanentsly stored with the network. The pointer returned by + this procedure contains the copy of the name, which should be used + in all network manipulation procedures.] SideEffects [] SeeAlso [] ***********************************************************************/ -char * Abc_ObjName( Abc_Obj_t * pObj ) +char * Abc_NtkRegisterName( Abc_Ntk_t * pNtk, char * pName ) { - return Nm_ManCreateUniqueName( pObj->pNtk->pManName, pObj->Id ); + char * pRegName; + if ( pName == NULL ) return NULL; + pRegName = Extra_MmFlexEntryFetch( pNtk->pMmNames, strlen(pName) + 1 ); + strcpy( pRegName, pName ); + return pRegName; } /**Function************************************************************* - Synopsis [Assigns the given name to the object.] + Synopsis [Registers the name with the string memory manager.] - 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.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ) +char * Abc_NtkRegisterNamePlus( Abc_Ntk_t * pNtk, char * pName, char * pSuffix ) { - assert( pName != NULL ); - return Nm_ManStoreIdName( pObj->pNtk->pManName, pObj->Id, pObj->Type, pName, pSuffix ); + char * pRegName; + assert( pName && pSuffix ); + pRegName = Extra_MmFlexEntryFetch( pNtk->pMmNames, strlen(pName) + strlen(pSuffix) + 1 ); + sprintf( pRegName, "%s%s", pName, pSuffix ); + return pRegName; +} + +/**Function************************************************************* + + Synopsis [Gets the long name of the object.] + + Description [The temporary 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 ) +{ + static char Buffer[500]; + char * pName; + + // check if the object is in the lookup table + if ( stmm_lookup( pObj->pNtk->tObj2Name, (char *)pObj, &pName ) ) + return pName; + + // consider network types + if ( Abc_NtkIsNetlist(pObj->pNtk) ) + { + // in a netlist, nets have names, nodes have no names + if ( Abc_ObjIsNode(pObj) ) + pObj = Abc_ObjFanout0(pObj); + assert( Abc_ObjIsNet(pObj) ); + // if the name is not given, invent it + if ( pObj->pData ) + sprintf( Buffer, "%s", pObj->pData ); + else + sprintf( Buffer, "[%d]", pObj->Id ); // make sure this name is unique!!! + } + else + { + // in a logic network, PI/PO/latch names are stored in the hash table + // internal nodes have made up names + assert( Abc_ObjIsNode(pObj) || Abc_ObjIsLatch(pObj) ); + sprintf( Buffer, "[%d]", pObj->Id ); + } + return Buffer; } /**Function************************************************************* @@ -88,7 +136,62 @@ char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ) /**Function************************************************************* - Synopsis [Returns the dummy PI name.] + Synopsis [Finds a unique name for the node.] + + Description [If the name exists, tries appending numbers to it until + it becomes unique.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjNameUnique( Abc_Ntk_t * pNtk, char * pName ) +{ + static char Buffer[1000]; + int Counter; + assert( 0 ); + if ( !stmm_is_member( pNtk->tName2Net, pName ) ) + return pName; + for ( Counter = 1; ; Counter++ ) + { + sprintf( Buffer, "%s_%d", pName, Counter ); + if ( !stmm_is_member( pNtk->tName2Net, Buffer ) ) + return Buffer; + } + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Adds new name to the network.] + + Description [The new object (pObjNew) is a PI, PO or latch. The name + is registered and added to the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NtkLogicStoreName( Abc_Obj_t * pObjNew, char * pNameOld ) +{ + char * pNewName; + assert( Abc_ObjIsCio(pObjNew) ); + // get the new name + pNewName = Abc_NtkRegisterName( pObjNew->pNtk, pNameOld ); + // add the name to the table + if ( stmm_insert( pObjNew->pNtk->tObj2Name, (char *)pObjNew, pNewName ) ) + { + assert( 0 ); // the object is added for the second time + } + return pNewName; +} + +/**Function************************************************************* + + Synopsis [Adds new name to the network.] Description [] @@ -97,73 +200,73 @@ char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ) SeeAlso [] ***********************************************************************/ -char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ) +char * Abc_NtkLogicStoreNamePlus( Abc_Obj_t * pObjNew, char * pNameOld, char * pSuffix ) { - static char Buffer[100]; - sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); - return Buffer; + char * pNewName; + assert( pSuffix ); + assert( Abc_ObjIsCio(pObjNew) ); + // get the new name + pNewName = Abc_NtkRegisterNamePlus( pObjNew->pNtk, pNameOld, pSuffix ); + // add the name to the table + if ( stmm_insert( pObjNew->pNtk->tObj2Name, (char *)pObjNew, pNewName ) ) + { + assert( 0 ); // the object is added for the second time + } + return pNewName; } /**Function************************************************************* - Synopsis [Tranfers names to the old network.] + Synopsis [Creates the name arrays from the old network.] - Description [Assumes that the new nodes are attached using pObj->pCopy.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +void Abc_NtkCreateCioNamesTable( Abc_Ntk_t * pNtk ) { 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 ); + assert( Abc_NtkIsNetlist(pNtk) ); + assert( st_count(pNtk->tObj2Name) == 0 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkLogicStoreName( pObj, Abc_ObjFanout0(pObj)->pData ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkLogicStoreName( pObj, Abc_ObjFanin0(pObj)->pData ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NtkLogicStoreName( pObj, Abc_ObjFanout0(pObj)->pData ); } /**Function************************************************************* - Synopsis [Tranfers names to the old network.] + Synopsis [Duplicates the name arrays.] - Description [Assumes that the new nodes are attached using pObj->pCopy.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +void Abc_NtkDupCioNamesTable( 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 ); + assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); + assert( st_count(pNtk->tObj2Name) > 0 ); + assert( st_count(pNtkNew->tObj2Name) == 0 ); + // copy the CI/CO names if given + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkLogicStoreName( Abc_NtkPi(pNtkNew,i), Abc_ObjName(pObj) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkLogicStoreName( Abc_NtkPo(pNtkNew,i), Abc_ObjName(pObj) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NtkLogicStoreName( Abc_NtkLatch(pNtkNew,i), Abc_ObjName(pObj) ); } /**Function************************************************************* @@ -184,7 +287,7 @@ Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ) int i; vNodes = Vec_PtrAlloc( 100 ); Abc_ObjForEachFanin( pNode, pFanin, i ) - Vec_PtrPush( vNodes, Extra_UtilStrsav(Abc_ObjName(pFanin)) ); + Vec_PtrPush( vNodes, util_strsav(Abc_ObjName(pFanin)) ); return vNodes; } @@ -219,7 +322,7 @@ Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ) Buffer[1] = '0' + i/26; Buffer[2] = 0; } - Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); + Vec_PtrPush( vNames, util_strsav(Buffer) ); } return vNames; } @@ -312,38 +415,42 @@ 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)); + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); // order objects alphabetically - qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), + qsort( pNtk->vCis->pArray, pNtk->nPis, 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 *), + qsort( pNtk->vCos->pArray, pNtk->nPos, 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 *), + { + qsort( pNtk->vLats->pArray, pNtk->nLatches, sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareNames ); - // order CIs/COs first PIs/POs(Asserts) then latches - Abc_NtkOrderCisCos( pNtk ); + // add latches to make COs + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Vec_PtrWriteEntry( pNtk->vCis, pNtk->nPis + i, pObj ); + Vec_PtrWriteEntry( pNtk->vCos, pNtk->nPos + i, pObj ); + } + } // 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 ) + Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pCopy = NULL; } /**Function************************************************************* - Synopsis [Adds dummy names.] + Synopsis [] Description [] @@ -352,112 +459,41 @@ void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ) SeeAlso [] ***********************************************************************/ -void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ) +void Abc_NtkShortNames( Abc_Ntk_t * pNtk ) { + stmm_table * tObj2NameNew; 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 [] + char Buffer[100]; + char * pNameNew; + int Length, i; -***********************************************************************/ -void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int nDigits, i; - nDigits = Extra_Base10Log( Abc_NtkPoNum(pNtk) ); + tObj2NameNew = stmm_init_table(stmm_ptrcmp, stmm_ptrhash); + // create new names and add them to the table + Length = Extra_Base10Log( Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + sprintf( Buffer, "pi%0*d", Length, i ); + pNameNew = Abc_NtkRegisterName( pNtk, Buffer ); + stmm_insert( tObj2NameNew, (char *)pObj, pNameNew ); + } + // create new names and add them to the table + Length = 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 ); + sprintf( Buffer, "po%0*d", Length, i ); + pNameNew = Abc_NtkRegisterName( pNtk, Buffer ); + stmm_insert( tObj2NameNew, (char *)pObj, pNameNew ); } -/* - nDigits = Extra_Base10Log( Abc_NtkBlackboxNum(pNtk) ); - Abc_NtkForEachBlackbox( pNtk, pObj, i ) + // create new names and add them to the table + Length = Extra_Base10Log( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( 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) ); + sprintf( Buffer, "lat%0*d", Length, i ); + pNameNew = Abc_NtkRegisterName( pNtk, Buffer ); + stmm_insert( tObj2NameNew, (char *)pObj, pNameNew ); } -*/ -} - -/**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 ); + stmm_free_table( pNtk->tObj2Name ); + pNtk->tObj2Name = tObj2NameNew; } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcNetlist.c b/src/base/abc/abcNetlist.c index 26b88c68..08ee93bb 100644 --- a/src/base/abc/abcNetlist.c +++ b/src/base/abc/abcNetlist.c @@ -19,19 +19,13 @@ ***********************************************************************/ #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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -45,37 +39,33 @@ static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ); SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ) +Abc_Ntk_t * Abc_NtkNetlistToLogic( 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 ); + if ( !Abc_NtkHasMapping(pNtk) ) + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP ); + else + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_MAP ); // duplicate the nodes Abc_NtkForEachNode( pNtk, pObj, i ) - Abc_NtkDupObj(pNtkNew, pObj, 0); + Abc_NtkDupObj(pNtkNew, pObj); // 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 + // fix the problem with CO pointing directing to CIs Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // duplicate EXDC if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc ); + pNtkNew->pExdc = Abc_NtkNetlistToLogic( pNtk->pExdc ); if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" ); + fprintf( stdout, "Abc_NtkNetlistToLogic(): Network check has failed.\n" ); return pNtkNew; } @@ -90,18 +80,31 @@ Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ) +Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew, * pNtkTemp; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) || Abc_NtkIsSeq(pNtk) ); if ( Abc_NtkIsStrash(pNtk) ) { pNtkTemp = Abc_NtkAigToLogicSop(pNtk); - pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); + pNtkNew = Abc_NtkLogicSopToNetlist( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + } + else if ( Abc_NtkIsSeq(pNtk) ) + { + pNtkTemp = Abc_NtkSeqToLogicSop(pNtk); + pNtkNew = Abc_NtkLogicSopToNetlist( pNtkTemp ); Abc_NtkDelete( pNtkTemp ); - return pNtkNew; } - return Abc_NtkLogicToNetlist( pNtk ); + else if ( Abc_NtkIsBddLogic(pNtk) ) + { + Abc_NtkBddToSop(pNtk); + pNtkNew = Abc_NtkLogicSopToNetlist( pNtk ); + Abc_NtkSopToBdd(pNtk); + } + else + pNtkNew = Abc_NtkLogicSopToNetlist( pNtk ); + return pNtkNew; } /**Function************************************************************* @@ -115,12 +118,12 @@ Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ) +Abc_Ntk_t * Abc_NtkLogicToNetlistBench( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew, * pNtkTemp; assert( Abc_NtkIsStrash(pNtk) ); pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk ); - pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); + pNtkNew = Abc_NtkLogicSopToNetlist( pNtkTemp ); Abc_NtkDelete( pNtkTemp ); return pNtkNew; } @@ -140,31 +143,24 @@ Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) +Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin; + char * pNameCo; int i, k; assert( Abc_NtkIsLogic(pNtk) ); + assert( Abc_NtkLogicHasSimpleCos(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 ); - } + if ( Abc_NtkIsBddLogic(pNtk) ) + Abc_NtkBddToSop(pNtk); // start the netlist by creating PI/PO/Latch objects - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); + if ( Abc_NtkIsSopLogic(pNtk) ) + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_NETLIST, ABC_FUNC_SOP ); + else + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_NETLIST, ABC_FUNC_BDD ); // create the CI nets and remember them in the new CI nodes Abc_NtkForEachCi( pNtk, pObj, i ) { @@ -174,7 +170,7 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) } // duplicate all nodes Abc_NtkForEachNode( pNtk, pObj, i ) - Abc_NtkDupObj(pNtkNew, pObj, 0); + Abc_NtkDupObj(pNtkNew, pObj); // first add the nets to the CO drivers Abc_NtkForEachCo( pNtk, pObj, i ) { @@ -186,21 +182,18 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) 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 ); - } + // the driver is a node + + // get the CO name + pNameCo = Abc_ObjIsPo(pObj)? Abc_ObjName(pObj) : Abc_ObjNameSuffix( pObj, "_in" ); + // make sure CO has a unique name + assert( Abc_NtkFindNet( pNtkNew, pNameCo ) == NULL ); + // create the CO net and connect it to CO + pNet = Abc_NtkFindOrCreateNet( pNtkNew, pNameCo ); + 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; } // create the missing nets Abc_NtkForEachNode( pNtk, pObj, i ) @@ -208,7 +201,7 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) 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 + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); Abc_ObjAddFanin( pNet, pObj->pCopy ); pObj->pCopy->pCopy = pNet; } @@ -218,9 +211,9 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); // duplicate EXDC if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc ); + pNtkNew->pExdc = Abc_NtkLogicToNetlist( pNtk->pExdc ); if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" ); + fprintf( stdout, "Abc_NtkLogicSopToNetlist(): Network check has failed.\n" ); return pNtkNew; } @@ -239,40 +232,40 @@ 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); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP ); + // create the constant node + Abc_NtkDupConst1( pNtk, pNtkNew ); // duplicate the nodes and create node functions Abc_NtkForEachNode( pNtk, pObj, i ) { - Abc_NtkDupObj(pNtkNew, pObj, 0); + if ( Abc_NodeIsConst(pObj) ) + continue; + Abc_NtkDupObj(pNtkNew, pObj); 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) ) + if ( Abc_NodeIsConst(pObj) ) + continue; + if ( !Abc_NodeIsAigChoice(pObj) ) continue; // create an OR gate pNodeNew = Abc_NtkCreateNode(pNtkNew); // add fanins - vInts = Vec_IntAlloc( 10 ); + Vec_IntClear( pNtk->vIntTemp ); for ( pFanin = pObj; pFanin; pFanin = pFanin->pData ) { - Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) ); + Vec_IntPush( pNtk->vIntTemp, (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) ); + pNodeNew->pData = Abc_SopCreateOrMultiCube( pNtkNew->pManFunc, pNtk->vIntTemp->nSize, pNtk->vIntTemp->pArray ); // set the new node pObj->pCopy->pCopy = pNodeNew; - Vec_IntFree( vInts ); } // connect the internal nodes Abc_NtkForEachNode( pNtk, pObj, i ) @@ -282,17 +275,7 @@ Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ) 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 ); - } - + Abc_NtkFinalize( pNtk, pNtkNew ); // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // duplicate the EXDC Ntk @@ -329,26 +312,25 @@ Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * 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 ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP ); + // create the constant node + Abc_NtkDupConst1( pNtk, pNtkNew ); // 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 ); + pObj->pCopy->pCopy = Abc_NodeCreateInv( 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_NodeIsConst(pObj) ) + { + Abc_NtkDupObj( pNtkNew, pObj ); + pObj->pCopy->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, 2 ); + } if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) - pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + pObj->pCopy->pCopy = Abc_NodeCreateInv( pNtkNew, pObj->pCopy ); } // connect the objects Vec_PtrForEachEntry( vNodes, pObj, i ) @@ -379,31 +361,6 @@ Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ) 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 index d78a3a6a..5c199141 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -19,7 +19,6 @@ ***********************************************************************/ #include "abc.h" -#include "abcInt.h" #include "main.h" #include "mio.h" @@ -27,8 +26,10 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#define ABC_NUM_STEPS 10 + //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -42,7 +43,7 @@ SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ) +Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func ) { Abc_Ntk_t * pNtk; pNtk = ALLOC( Abc_Ntk_t, 1 ); @@ -51,35 +52,32 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan 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->vLats = Vec_PtrAlloc( 100 ); pNtk->vCis = Vec_PtrAlloc( 100 ); pNtk->vCos = Vec_PtrAlloc( 100 ); - pNtk->vBoxes = Vec_PtrAlloc( 100 ); + pNtk->vPtrTemp = Vec_PtrAlloc( 100 ); + pNtk->vIntTemp = Vec_IntAlloc( 100 ); + pNtk->vStrTemp = Vec_StrAlloc( 100 ); + // start the hash table + pNtk->tName2Net = stmm_init_table(strcmp, stmm_strhash); + pNtk->tObj2Name = stmm_init_table(stmm_ptrcmp, stmm_ptrhash); // start the memory managers - pNtk->pMmObj = fUseMemMan? Extra_MmFixedStart( sizeof(Abc_Obj_t) ) : NULL; - pNtk->pMmStep = fUseMemMan? Extra_MmStepStart( ABC_NUM_STEPS ) : NULL; + pNtk->pMmNames = Extra_MmFlexStart(); + pNtk->pMmObj = Extra_MmFixedStart( sizeof(Abc_Obj_t) ); + pNtk->pMmStep = Extra_MmStepStart( ABC_NUM_STEPS ); // 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) ) + if ( Abc_NtkHasSop(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(); + pNtk->pManFunc = Abc_AigAlloc( pNtk ); else if ( Abc_NtkHasMapping(pNtk) ) - pNtk->pManFunc = Abc_FrameReadLibGen(); - else if ( !Abc_NtkHasBlackbox(pNtk) ) + pNtk->pManFunc = Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()); + else assert( 0 ); - // name manager - pNtk->pManName = Nm_ManCreate( 200 ); - // attribute manager - pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); return pNtk; } @@ -97,44 +95,38 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan 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; + Abc_Obj_t * pObj, * pObjNew; + int 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 ); + pNtkNew = Abc_NtkAlloc( Type, Func ); // 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 + pNtkNew->pName = util_strsav(pNtk->pName); + pNtkNew->pSpec = util_strsav(pNtk->pSpec); + // clone the PIs/POs/latches Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkDupObj(pNtkNew, pObj); 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 ); + Abc_NtkDupObj(pNtkNew, pObj); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pObjNew = Abc_NtkDupObj(pNtkNew, pObj); + Vec_PtrPush( pNtkNew->vCis, pObjNew ); + Vec_PtrPush( pNtkNew->vCos, pObjNew ); + } + // clean the node copy fields + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = NULL; // transfer the names -// Abc_NtkTrasferNames( pNtk, pNtkNew ); + Abc_NtkDupCioNamesTable( 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.] + Synopsis [Finalizes the network using the existing network as a model.] Description [] @@ -143,44 +135,17 @@ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_ SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) +void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj; + Abc_Obj_t * pObj, * pDriver, * pDriverNew; 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 ) + // set the COs of the strashed network + Abc_NtkForEachCo( pNtk, pObj, i ) { - if ( Abc_ObjIsLatch(pObj) ) - continue; - Abc_NtkDupBox(pNtkNew, pObj, 1); + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); + pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); + Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); } - // 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************************************************************* @@ -194,7 +159,7 @@ Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc SeeAlso [] ***********************************************************************/ -void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +void Abc_NtkFinalizeRegular( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { Abc_Obj_t * pObj, * pDriver, * pDriverNew; int i; @@ -202,11 +167,35 @@ void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) Abc_NtkForEachCo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); - pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); + pDriverNew = pDriver->pCopy; Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); } } +/**Function************************************************************* + + Synopsis [Finalizes the network adding latches to CI/CO lists and creates their names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinalizeLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch; + int i; + // set the COs of the strashed network + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + Vec_PtrPush( pNtk->vCis, pLatch ); + Vec_PtrPush( pNtk->vCos, pLatch ); + Abc_NtkLogicStoreName( pLatch, Abc_ObjNameSuffix(pLatch, "L") ); + } +} + /**Function************************************************************* Synopsis [Starts a new network using existing network as a model.] @@ -222,15 +211,10 @@ 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 ); + pNtkNew = Abc_NtkAlloc( ABC_TYPE_NETLIST, ABC_FUNC_SOP ); // 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"); - } + pNtkNew->pName = util_strsav( pName ); + pNtkNew->pSpec = util_strsav( pName ); return pNtkNew; } @@ -247,50 +231,19 @@ Abc_Ntk_t * Abc_NtkStartRead( char * pName ) ***********************************************************************/ void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ) { - Abc_Obj_t * pBox, * pObj, * pTerm, * pNet; + Abc_Obj_t * pLatch; 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 ); + // create the names table + Abc_NtkCreateCioNamesTable( pNtk ); + // add latches to the CI/CO arrays + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + Vec_PtrPush( pNtk->vCis, pLatch ); + Vec_PtrPush( pNtk->vCos, pLatch ); + } } /**Function************************************************************* @@ -314,47 +267,30 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) // 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) ); - } + if ( Abc_NtkHasAig(pNtk) ) + Abc_AigDup( pNtk->pManFunc, pNtkNew->pManFunc ); 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); + Abc_NtkDupObj(pNtkNew, pObj); // 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 ); + 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.] + Synopsis [Creates the network composed of one output.] Description [] @@ -363,173 +299,24 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) 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_Ntk_t * Abc_NtkSplitOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAllCis ) { - 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; + Abc_Obj_t * pObj, * pFanin; char Buffer[1000]; int i, k; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); + assert( Abc_ObjIsCo(pNode) ); // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc ); // set the name - sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); - pNtkNew->pName = Extra_UtilStrsav(Buffer); + sprintf( Buffer, "%s_%s", pNtk->pName, Abc_ObjName(pNode) ); + pNtkNew->pName = util_strsav(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) + // collect the nodes in the TFI of the output vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 ); // create the PIs Abc_NtkForEachCi( pNtk, pObj, i ) @@ -537,79 +324,12 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNode 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 ); + Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) ); } } - // 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 ); - } - } + Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkNew->pManFunc); // copy the nodes Vec_PtrForEachEntry( vNodes, pObj, i ) @@ -621,160 +341,26 @@ Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fU } else { - Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkDupObj( pNtkNew, pObj ); 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 ); + // add the PO corresponding to this output + pNode->pCopy = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNode->pCopy, Abc_ObjFanin0(pNode)->pCopy ); + Abc_NtkLogicStoreName( pNode->pCopy, Abc_ObjName(pNode) ); if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" ); + fprintf( stdout, "Abc_NtkSplitOutput(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* - Synopsis [Creates the miter composed of one multi-output cone.] + Synopsis [Creates the network composed of one output.] Description [] @@ -783,7 +369,7 @@ Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNode SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) +Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; @@ -794,8 +380,8 @@ Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t // start the network Abc_NtkCleanCopy( pNtk ); - pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG ); + pNtkNew->pName = util_strsav(pNtk->pName); // collect the nodes in the TFI of the output vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize ); @@ -803,21 +389,18 @@ Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t Abc_NtkForEachCi( pNtk, pObj, i ) { pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) ); } // copy the nodes Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 ); + pObj->pCopy = Abc_NodeStrash( pNtkNew->pManFunc, pObj ); Vec_PtrFree( vNodes ); // add the PO - pFinal = Abc_AigConst1( pNtkNew ); + pFinal = Abc_AigConst1( pNtkNew->pManFunc ); Vec_PtrForEachEntry( vRoots, pObj, i ) { - if ( Abc_ObjIsCo(pObj) ) - pOther = Abc_ObjFanin0(pObj)->pCopy; - else - pOther = pObj->pCopy; + pOther = pObj->pCopy; if ( Vec_IntEntry(vValues, i) == 0 ) pOther = Abc_ObjNot(pOther); pFinal = Abc_AigAnd( pNtkNew->pManFunc, pFinal, pOther ); @@ -826,15 +409,15 @@ Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t // add the PO corresponding to this output pNodePo = Abc_NtkCreatePo( pNtkNew ); Abc_ObjAddFanin( pNodePo, pFinal ); - Abc_ObjAssignName( pNodePo, "miter", NULL ); + Abc_NtkLogicStoreName( pNodePo, "miter" ); if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" ); + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* - Synopsis [Creates the network composed of one node.] + Synopsis [Deletes the Ntk.] Description [] @@ -843,71 +426,30 @@ Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) +Abc_Ntk_t * Abc_NtkSplitNode( 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)); + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc ); + pNtkNew->pName = util_strsav(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 ); + Abc_NtkLogicStoreName( pFanin->pCopy, Abc_ObjName(pFanin) ); } // duplicate and connect the node - pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 ); + pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode ); 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 ); + Abc_NtkLogicStoreName( pNodePo, Abc_ObjName(pNode) ); if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); + fprintf( stdout, "Abc_NtkSplitNode(): Network check has failed.\n" ); return pNtkNew; } @@ -925,107 +467,64 @@ Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) 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 ) + if ( pObj->vFanouts.nCap * 4 > LargePiece ) FREE( pObj->vFanouts.pArray ); - // these flags should be always zero - // if this is not true, something is wrong somewhere + // check that the other things are okay 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 ); - } + + // dereference the BDDs + if ( Abc_NtkHasBdd(pNtk) ) + Abc_NtkForEachNode( pNtk, pObj, i ) + Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData ); + FREE( pNtk->pName ); + FREE( pNtk->pSpec ); + // copy the EXDC Ntk + if ( pNtk->pExdc ) + Abc_NtkDelete( pNtk->pExdc ); // free the arrays - Vec_PtrFree( pNtk->vPios ); - Vec_PtrFree( pNtk->vPis ); - Vec_PtrFree( pNtk->vPos ); + Vec_PtrFree( pNtk->vObjs ); + Vec_PtrFree( pNtk->vLats ); 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 ); - FREE( pNtk->pModel ); - FREE( pNtk->pSeqModel ); + Vec_PtrFree( pNtk->vPtrTemp ); + Vec_IntFree( pNtk->vIntTemp ); + Vec_StrFree( pNtk->vStrTemp ); + // free the hash table of Obj name into Obj ID + stmm_free_table( pNtk->tName2Net ); + stmm_free_table( pNtk->tObj2Name ); TotalMemory = 0; - TotalMemory += pNtk->pMmObj? Extra_MmFixedReadMemUsage(pNtk->pMmObj) : 0; - TotalMemory += pNtk->pMmStep? Extra_MmStepReadMemUsage(pNtk->pMmStep) : 0; + TotalMemory += Extra_MmFlexReadMemUsage(pNtk->pMmNames); + TotalMemory += Extra_MmFixedReadMemUsage(pNtk->pMmObj); + TotalMemory += Extra_MmStepReadMemUsage(pNtk->pMmStep); // 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 ); + Extra_MmFlexStop ( pNtk->pMmNames, 0 ); + Extra_MmFixedStop( pNtk->pMmObj, 0 ); + Extra_MmStepStop ( pNtk->pMmStep, 0 ); // 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 ); + if ( Abc_NtkHasSop(pNtk) ) + Extra_MmFlexStop( pNtk->pManFunc, 0 ); 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) ) + Abc_AigFree( pNtk->pManFunc ); + else if ( !Abc_NtkHasMapping(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 ); } @@ -1046,9 +545,6 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) 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 ) @@ -1056,24 +552,28 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) if ( Abc_ObjFaninNum(pNet) > 0 ) continue; // add the constant 0 driver - pNode = Abc_NtkCreateNodeConst0( pNtk ); + pNode = Abc_NtkCreateNode( pNtk ); + // set the constant function + Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, " 0\n") ); // add the fanout net Abc_ObjAddFanin( pNet, pNode ); // add the net to those for which the warning will be printed - Vec_PtrPush( vNets, pNet ); + Vec_PtrPush( vNets, pNet->pData ); } // 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( "Constant-zero drivers were added to %d non-driven nets:\n", vNets->nSize ); + for ( i = 0; i < vNets->nSize; i++ ) { - printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) ); - if ( i == 3 ) + if ( i == 0 ) + printf( "%s", vNets->pArray[i] ); + else if ( i == 1 ) + printf( ", %s", vNets->pArray[i] ); + else if ( i == 2 ) { - if ( Vec_PtrSize(vNets) > 3 ) - printf( " ..." ); + printf( ", %s, etc.", vNets->pArray[i] ); break; } } @@ -1083,150 +583,6 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) } -/**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 ); -} //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c index 7a995c71..40c6e7a5 100644 --- a/src/base/abc/abcObj.c +++ b/src/base/abc/abcObj.c @@ -19,7 +19,6 @@ ***********************************************************************/ #include "abc.h" -#include "abcInt.h" #include "main.h" #include "mio.h" @@ -28,12 +27,12 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Creates a new object.] + Synopsis [Creates a new Obj.] Description [] @@ -45,20 +44,17 @@ 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 ); + pObj = (Abc_Obj_t *)Extra_MmFixedEntryFetch( pNtk->pMmObj ); memset( pObj, 0, sizeof(Abc_Obj_t) ); + pObj->Id = -1; pObj->pNtk = pNtk; pObj->Type = Type; - pObj->Id = -1; return pObj; } /**Function************************************************************* - Synopsis [Recycles the object.] + Synopsis [Recycles the Obj.] Description [] @@ -70,22 +66,8 @@ Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) 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 ); + Extra_MmFixedEntryRecycle( pNtk->pMmObj, (char *)pObj ); } /**Function************************************************************* @@ -99,207 +81,49 @@ void Abc_ObjRecycle( Abc_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) +void Abc_ObjAdd( Abc_Obj_t * pObj ) { - Abc_Obj_t * pObj; - // create new object, assign ID, and add to the array - pObj = Abc_ObjAlloc( pNtk, Type ); + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( !Abc_ObjIsComplement(pObj) ); + // add to the array of objects 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) + if ( Abc_ObjIsNet(pObj) ) { - 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; + // add the name to the table + if ( pObj->pData && stmm_insert( pNtk->tName2Net, pObj->pData, (char *)pObj ) ) + { + printf( "Error: The net is already in the table...\n" ); + assert( 0 ); + } + pNtk->nNets++; } - 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) + else if ( Abc_ObjIsNode(pObj) ) { - 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; + pNtk->nNodes++; } - // 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 ) + else if ( Abc_ObjIsLatch(pObj) ) { - Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) - Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); + Vec_PtrPush( pNtk->vLats, pObj ); + pNtk->nLatches++; + } + else if ( Abc_ObjIsPi(pObj) ) + { + Vec_PtrPush( pNtk->vCis, pObj ); + pNtk->nPis++; + } + else if ( Abc_ObjIsPo(pObj) ) + { + Vec_PtrPush( pNtk->vCos, pObj ); + pNtk->nPos++; } else { - Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( !Abc_ObjIsPi(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) - Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); + assert( 0 ); } - 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 ); + assert( pObj->Id >= 0 ); } /**Function************************************************************* @@ -313,68 +137,37 @@ void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ) +Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) { 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 + pObjNew = Abc_ObjAlloc( pNtkNew, pObj->Type ); 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) ) + if ( Abc_NtkHasSop(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_NtkHasAig(pNtkNew) ) + assert( 0 ); } } else if ( Abc_ObjIsNet(pObj) ) // copy the name - { - } + pObjNew->pData = Abc_NtkRegisterName( pNtkNew, pObj->pData ); 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; + // add the object to the network + Abc_ObjAdd( pObjNew ); return pObjNew; } /**Function************************************************************* - Synopsis [Duplicates the latch with its input/output terminals.] + Synopsis [Creates a new constant node.] Description [] @@ -383,25 +176,48 @@ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName 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; -} +Abc_Obj_t * Abc_NtkDupConst1( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pConst1; + assert( Abc_NtkIsStrash(pNtkAig) ); + assert( Abc_NtkIsSopLogic(pNtkNew) ); + pConst1 = Abc_AigConst1(pNtkAig->pManFunc); + if ( Abc_ObjFanoutNum(pConst1) > 0 ) + pConst1->pCopy = Abc_NodeCreateConst1( pNtkNew ); + return pConst1->pCopy; +} + +/**Function************************************************************* + + Synopsis [Creates a new constant node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDupReset( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pReset, * pConst1; + assert( Abc_NtkIsStrash(pNtkAig) ); + assert( Abc_NtkIsSopLogic(pNtkNew) ); + pReset = Abc_AigReset(pNtkAig->pManFunc); + if ( Abc_ObjFanoutNum(pReset) > 0 ) + { + // create new latch with reset value 0 + pReset->pCopy = Abc_NtkCreateLatch( pNtkNew ); + // add constant node fanin to the latch + pConst1 = Abc_NodeCreateConst1( pNtkNew ); + Abc_ObjAddFanin( pReset->pCopy, pConst1 ); + } + return pReset->pCopy; +} /**Function************************************************************* - Synopsis [Clones the objects in the same network but does not assign its function.] + Synopsis [Deletes the object from the network.] Description [] @@ -410,17 +226,59 @@ Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj ) +void Abc_NtkDeleteObj( Abc_Obj_t * pObj ) { - Abc_Obj_t * pClone, * pFanin; + Vec_Ptr_t * vNodes = pObj->pNtk->vPtrTemp; + Abc_Ntk_t * pNtk = pObj->pNtk; int i; - pClone = Abc_NtkCreateObj( pObj->pNtk, pObj->Type ); - Abc_ObjForEachFanin( pObj, pFanin, i ) - Abc_ObjAddFanin( pClone, pFanin ); - return pClone; + + assert( !Abc_ObjIsComplement(pObj) ); + + // delete fanins and fanouts + 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] ); + + // remove from the list of objects + Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL ); + pObj->Id = (1<<26)-1; + pNtk->nObjs--; + + // perform specialized operations depending on the object type + if ( Abc_ObjIsNet(pObj) ) + { + // remove the net from the hash table of nets + if ( pObj->pData && !stmm_delete( pNtk->tName2Net, (char **)&pObj->pData, (char **)&pObj ) ) + { + printf( "Error: The net is not in the table...\n" ); + assert( 0 ); + } + pObj->pData = NULL; + pNtk->nNets--; + } + else if ( Abc_ObjIsNode(pObj) ) + { + if ( Abc_NtkHasBdd(pNtk) ) + Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData ); + pNtk->nNodes--; + } + else if ( Abc_ObjIsLatch(pObj) ) + { + pNtk->nLatches--; + } + else + assert( 0 ); + // recycle the net itself + Abc_ObjRecycle( pObj ); } + + + /**Function************************************************************* Synopsis [Returns the net with the given name.] @@ -434,22 +292,38 @@ Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj ) ***********************************************************************/ 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 ); + Abc_Obj_t * pObj, * pDriver; + int i, Num; + // check if the node is among CIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( strcmp( Abc_ObjName(pObj), pName ) == 0 ) + { + if ( i < Abc_NtkPiNum(pNtk) ) + printf( "Node \"%s\" is a primary input.\n", pName ); + else + printf( "Node \"%s\" is a latch output.\n", pName ); + return NULL; + } + } + // search the node among COs + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( strcmp( Abc_ObjName(pObj), pName ) == 0 ) + { + pDriver = Abc_ObjFanin0(pObj); + if ( !Abc_ObjIsNode(pDriver) ) + { + printf( "Node \"%s\" does not have logic associated with it.\n", pName ); + return NULL; + } + return pDriver; + } + } // find the internal node - if ( pName[0] != 'n' ) + if ( pName[0] != '[' || pName[strlen(pName)-1] != ']' ) { - printf( "Name \"%s\" is not found among CO or node names (internal names often look as \"n\").\n", pName ); + printf( "Name \"%s\" is not found among CIs/COs (internal name looks like this: \"[integer]\").\n", pName ); return NULL; } Num = atoi( pName + 1 ); @@ -472,6 +346,30 @@ Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ) return pObj; } +/**Function************************************************************* + + Synopsis [Returns the net with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNode; + int i; + // search the node among COs + Abc_NtkForEachCo( pNtk, pNode, i ) + { + if ( strcmp( Abc_ObjName(pNode), pName ) == 0 ) + return pNode; + } + return NULL; +} + /**Function************************************************************* Synopsis [Returns the net with the given name.] @@ -486,67 +384,77 @@ Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ) 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; + if ( stmm_lookup( pNtk->tName2Net, pName, (char**)&pNet ) ) + return pNet; + return NULL; } /**Function************************************************************* - Synopsis [Returns CI with the given name.] + Synopsis [Finds or creates the net.] - Description [] - - SideEffects [] + Description [] + + SideEffects [] - SeeAlso [] + SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ) +Abc_Obj_t * Abc_NtkFindOrCreateNet( 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; + Abc_Obj_t * pNet; + assert( Abc_NtkIsNetlist(pNtk) ); + if ( pNet = Abc_NtkFindNet( pNtk, pName ) ) + return pNet; + // create a new net + pNet = Abc_ObjAlloc( pNtk, ABC_OBJ_NET ); + pNet->pData = Abc_NtkRegisterName( pNtk, pName ); + Abc_ObjAdd( pNet ); + return pNet; } - + /**Function************************************************************* - Synopsis [Returns CO with the given name.] + Synopsis [Create the new node.] - Description [] - - SideEffects [] + Description [] + + SideEffects [] - SeeAlso [] + SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ) +Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) { - 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; + Abc_Obj_t * pObj; + pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_NODE ); + Abc_ObjAdd( pObj ); + return pObj; } + +/**Function************************************************************* + + Synopsis [Create the new node.] + + Description [] + + SideEffects [] + SeeAlso [] +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_PI ); + Abc_ObjAdd( pObj ); + return pObj; +} + /**Function************************************************************* - Synopsis [Finds or creates the net.] + Synopsis [Create the new node.] Description [] @@ -555,23 +463,17 @@ Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ) +Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ) { - 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; + Abc_Obj_t * pObj; + pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_PO ); + Abc_ObjAdd( pObj ); + return pObj; } /**Function************************************************************* - Synopsis [Creates constant 0 node.] + Synopsis [Create the new node.] Description [] @@ -580,27 +482,17 @@ Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ) +Abc_Obj_t * Abc_NtkCreateLatch( 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; + Abc_Obj_t * pObj; + pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_LATCH ); + Abc_ObjAdd( pObj ); + return pObj; } /**Function************************************************************* - Synopsis [Creates constant 1 node.] + Synopsis [Creates inverter.] Description [] @@ -609,20 +501,18 @@ Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ) +Abc_Obj_t * Abc_NodeCreateConst0( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( !Abc_NtkHasAig(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); - if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) - pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\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); + pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData ); else if ( Abc_NtkHasMapping(pNtk) ) - pNode->pData = Mio_LibraryReadConst1(Abc_FrameReadLibGen()); - else if ( !Abc_NtkHasBlackbox(pNtk) ) + pNode->pData = Mio_LibraryReadConst0(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())); + else assert( 0 ); return pNode; } @@ -638,20 +528,18 @@ Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) +Abc_Obj_t * Abc_NodeCreateConst1( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkHasAig(pNtk) ) + return Abc_AigConst1(pNtk->pManFunc); pNode = Abc_NtkCreateNode( pNtk ); - if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopRegister( pNtk->pManFunc, "0 1\n" ); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 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)); + pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData ); else if ( Abc_NtkHasMapping(pNtk) ) - pNode->pData = Mio_LibraryReadInv(Abc_FrameReadLibGen()); + pNode->pData = Mio_LibraryReadConst1(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())); else assert( 0 ); return pNode; @@ -659,7 +547,7 @@ Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) /**Function************************************************************* - Synopsis [Creates buffer.] + Synopsis [Creates inverter.] Description [] @@ -668,20 +556,18 @@ Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) +Abc_Obj_t * Abc_NodeCreateInv( 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 ); + pNode = Abc_NtkCreateNode( pNtk ); + Abc_ObjAddFanin( pNode, pFanin ); if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopRegister( pNtk->pManFunc, "1 1\n" ); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, "0 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); + pNode->pData = Cudd_Not(Cudd_bddIthVar(pNtk->pManFunc,0)), Cudd_Ref( pNode->pData ); else if ( Abc_NtkHasMapping(pNtk) ) - pNode->pData = Mio_LibraryReadBuf(Abc_FrameReadLibGen()); + pNode->pData = Mio_LibraryReadInv(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())); else assert( 0 ); return pNode; @@ -689,7 +575,7 @@ Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) /**Function************************************************************* - Synopsis [Creates AND.] + Synopsis [Creates buffer.] Description [] @@ -698,20 +584,18 @@ Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +Abc_Obj_t * Abc_NodeCreateBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) { 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] ); + Abc_ObjAddFanin( pNode, pFanin ); if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, "1 1\n" ); 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) ); + pNode->pData = Cudd_bddIthVar(pNtk->pManFunc,0), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadBuf(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())); else assert( 0 ); return pNode; @@ -719,7 +603,7 @@ Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) /**Function************************************************************* - Synopsis [Creates OR.] + Synopsis [Creates inverter.] Description [] @@ -728,20 +612,39 @@ Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +Abc_Obj_t * Abc_NodeCreateAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pNode; int i; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkIsLogic(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 ); + { + char * pSop; + pSop = Extra_MmFlexEntryFetch( pNtk->pManFunc, vFanins->nSize + 4 ); + for ( i = 0; i < vFanins->nSize; i++ ) + pSop[i] = '1'; + pSop[i++] = ' '; + pSop[i++] = '1'; + pSop[i++] = '\n'; + pSop[i++] = 0; + assert( i == vFanins->nSize + 4 ); + pNode->pData = pSop; + } 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) ); + { + DdManager * dd = pNtk->pManFunc; + DdNode * bFunc, * bTemp; + bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); + for ( i = 0; i < vFanins->nSize; i++ ) + { + bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(pNtk->pManFunc,i) ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + pNode->pData = bFunc; + } else assert( 0 ); return pNode; @@ -749,7 +652,7 @@ Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) /**Function************************************************************* - Synopsis [Creates EXOR.] + Synopsis [Creates inverter.] Description [] @@ -758,20 +661,39 @@ Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +Abc_Obj_t * Abc_NodeCreateOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pNode; int i; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkIsLogic(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) ); + { + char * pSop; + pSop = Extra_MmFlexEntryFetch( pNtk->pManFunc, vFanins->nSize + 4 ); + for ( i = 0; i < vFanins->nSize; i++ ) + pSop[i] = '0'; + pSop[i++] = ' '; + pSop[i++] = '0'; + pSop[i++] = '\n'; + pSop[i++] = 0; + assert( i == vFanins->nSize + 4 ); + pNode->pData = pSop; + } 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) ); + { + DdManager * dd = pNtk->pManFunc; + DdNode * bFunc, * bTemp; + bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); + for ( i = 0; i < vFanins->nSize; i++ ) + { + bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(pNtk->pManFunc,i) ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + pNode->pData = bFunc; + } else assert( 0 ); return pNode; @@ -779,7 +701,7 @@ Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) /**Function************************************************************* - Synopsis [Creates MUX.] + Synopsis [Creates inverter.] Description [] @@ -788,7 +710,7 @@ Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) 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 * Abc_NodeCreateMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ) { Abc_Obj_t * pNode; assert( Abc_NtkIsLogic(pNtk) ); @@ -800,17 +722,14 @@ Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_ 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.] + Synopsis [Clones the given node but does not assign the function.] Description [] @@ -819,15 +738,22 @@ Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_ 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; +Abc_Obj_t * Abc_NodeClone( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pClone, * pFanin; + int i; + assert( Abc_ObjIsNode(pNode) ); + pClone = Abc_NtkCreateNode( pNode->pNtk ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_ObjAddFanin( pClone, pFanin ); + return pClone; } + + /**Function************************************************************* - Synopsis [Returns 1 if the node is a constant 0 node.] + Synopsis [] Description [] @@ -839,25 +765,23 @@ bool Abc_NodeIsConst( Abc_Obj_t * pNode ) 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; + assert(Abc_ObjIsNode(pNode)); + assert(Abc_NodeIsConst(pNode)); 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); + return Abc_ObjNot(pNode) == Abc_AigConst1(pNode->pNtk->pManFunc); if ( Abc_NtkHasMapping(pNtk) ) - return pNode->pData == Mio_LibraryReadConst0(Abc_FrameReadLibGen()); + return pNode->pData == Mio_LibraryReadConst0(Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame())); assert( 0 ); return 0; } /**Function************************************************************* - Synopsis [Returns 1 if the node is a constant 1 node.] + Synopsis [] Description [] @@ -869,25 +793,23 @@ bool Abc_NodeIsConst0( Abc_Obj_t * pNode ) 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; + assert(Abc_ObjIsNode(pNode)); + assert(Abc_NodeIsConst(pNode)); 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); + return pNode == Abc_AigConst1(pNode->pNtk->pManFunc); if ( Abc_NtkHasMapping(pNtk) ) - return pNode->pData == Mio_LibraryReadConst1(Abc_FrameReadLibGen()); + return pNode->pData == Mio_LibraryReadConst1(Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame())); assert( 0 ); return 0; } /**Function************************************************************* - Synopsis [Returns 1 if the node is a buffer.] + Synopsis [] Description [] @@ -899,8 +821,7 @@ bool Abc_NodeIsConst1( Abc_Obj_t * pNode ) bool Abc_NodeIsBuf( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); + assert(Abc_ObjIsNode(pNode)); if ( Abc_ObjFaninNum(pNode) != 1 ) return 0; if ( Abc_NtkHasSop(pNtk) ) @@ -908,16 +829,16 @@ bool Abc_NodeIsBuf( Abc_Obj_t * pNode ) if ( Abc_NtkHasBdd(pNtk) ) return !Cudd_IsComplement(pNode->pData); if ( Abc_NtkHasAig(pNtk) ) - return !Hop_IsComplement(pNode->pData); + return 0; if ( Abc_NtkHasMapping(pNtk) ) - return pNode->pData == Mio_LibraryReadBuf(Abc_FrameReadLibGen()); + return pNode->pData == Mio_LibraryReadBuf(Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame())); assert( 0 ); return 0; } /**Function************************************************************* - Synopsis [Returns 1 if the node is an inverter.] + Synopsis [] Description [] @@ -929,8 +850,7 @@ bool Abc_NodeIsBuf( Abc_Obj_t * pNode ) bool Abc_NodeIsInv( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); + assert(Abc_ObjIsNode(pNode)); if ( Abc_ObjFaninNum(pNode) != 1 ) return 0; if ( Abc_NtkHasSop(pNtk) ) @@ -938,38 +858,13 @@ bool Abc_NodeIsInv( Abc_Obj_t * pNode ) if ( Abc_NtkHasBdd(pNtk) ) return Cudd_IsComplement(pNode->pData); if ( Abc_NtkHasAig(pNtk) ) - return Hop_IsComplement(pNode->pData); + return 0; if ( Abc_NtkHasMapping(pNtk) ) - return pNode->pData == Mio_LibraryReadInv(Abc_FrameReadLibGen()); + return pNode->pData == Mio_LibraryReadInv(Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame())); 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 index 604c5ffa..47618bf4 100644 --- a/src/base/abc/abcRefs.c +++ b/src/base/abc/abcRefs.c @@ -24,11 +24,11 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ); +static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes ); static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -45,13 +45,12 @@ static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ); int Abc_NodeMffcSize( Abc_Obj_t * pNode ) { int nConeSize1, nConeSize2; -// assert( Abc_NtkIsStrash(pNode->pNtk) ); -// assert( !Abc_ObjIsComplement( pNode ) ); + 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 + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, NULL ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference assert( nConeSize1 == nConeSize2 ); assert( nConeSize1 > 0 ); return nConeSize1; @@ -71,7 +70,6 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode ) 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 ) @@ -94,21 +92,47 @@ int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ -int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ) +int Abc_NodeMffcLabel( 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 + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1, NULL ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference assert( nConeSize1 == nConeSize2 ); assert( nConeSize1 > 0 ); return nConeSize1; } +/**Function************************************************************* + + Synopsis [Collects the nodes in MFFC in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + int nConeSize1, nConeSize2; + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + vNodes = Vec_PtrAlloc( 8 ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return vNodes; + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, vNodes ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return vNodes; +} + /**Function************************************************************* Synopsis [References/references the node and returns MFFC size.] @@ -120,13 +144,16 @@ int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ -int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ) +int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pNode0, * pNode1; int Counter; // label visited nodes if ( fLabel ) Abc_NodeSetTravIdCurrent( pNode ); + // collect visited nodes + if ( vNodes ) + Vec_PtrPush( vNodes, pNode ); // skip the CI if ( Abc_ObjIsCi(pNode) ) return 0; @@ -137,23 +164,22 @@ int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ) if ( fReference ) { if ( pNode0->vFanouts.nSize++ == 0 ) - Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); + Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes ); if ( pNode1->vFanouts.nSize++ == 0 ) - Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); + Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes ); } else { assert( pNode0->vFanouts.nSize > 0 ); assert( pNode1->vFanouts.nSize > 0 ); if ( --pNode0->vFanouts.nSize == 0 ) - Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); + Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes ); if ( --pNode1->vFanouts.nSize == 0 ) - Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); + Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes ); } return Counter; } - /**Function************************************************************* Synopsis [References/references the node and returns MFFC size.] @@ -195,256 +221,6 @@ int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool 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 index 40d1dcad..20a64246 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -30,11 +30,11 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern void Abc_ShowFile( char * FileNameDot ); +static void Abc_ShowFile( char * FileNameDot ); static void Abc_ShowGetFileName( char * pName, char * pBuffer ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -77,6 +77,47 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) Abc_ShowFile( FileNameDot ); } +/**Function************************************************************* + + Synopsis [Visualizes AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShowAig( Abc_Ntk_t * pNtk ) +{ + FILE * pFile; + Abc_Obj_t * pNode; + Vec_Ptr_t * vNodes; + char FileNameDot[200]; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + // 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; + } + + // collect all nodes in the network + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + // write the DOT file + Io_WriteDot( pNtk, vNodes, NULL, FileNameDot ); + Vec_PtrFree( vNodes ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + /**Function************************************************************* Synopsis [Visualizes a reconvergence driven cut at the node.] @@ -129,7 +170,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) // 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 ); + Io_WriteDot( pNode->pNtk, vInside, vCutSmall, FileNameDot ); // stop the cut computation manager Abc_NtkManCutStop( p ); @@ -137,59 +178,6 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) 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************************************************************* diff --git a/src/base/abc/abcSop.c b/src/base/abc/abcSop.c index 106901ab..28e92889 100644 --- a/src/base/abc/abcSop.c +++ b/src/base/abc/abcSop.c @@ -28,7 +28,7 @@ 01- 1 1-1 1 - is the string: "01- 1\n1-1 1\n" where '\n' is a single char. + is the string: "01- 1/n1-1 1/n" where '/n' is a single char. */ //////////////////////////////////////////////////////////////////////// @@ -36,7 +36,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -61,7 +61,7 @@ char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ) /**Function************************************************************* - Synopsis [Creates the constant 1 cover with the given number of variables and cubes.] + Synopsis [Starts the constant 1 cover with the given number of variables and cubes.] Description [] @@ -92,7 +92,7 @@ char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ) /**Function************************************************************* - Synopsis [Creates the constant 1 cover with 0 variables.] + Synopsis [Starts the constant 1 cover with 0 variables.] Description [] @@ -108,7 +108,7 @@ char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan ) /**Function************************************************************* - Synopsis [Creates the constant 1 cover with 0 variables.] + Synopsis [Starts the constant 1 cover with 0 variables.] Description [] @@ -124,7 +124,7 @@ char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan ) /**Function************************************************************* - Synopsis [Creates the AND2 cover.] + Synopsis [Starts the AND2 cover.] Description [] @@ -147,7 +147,7 @@ char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ) /**Function************************************************************* - Synopsis [Creates the multi-input AND cover.] + Synopsis [Starts the multi-input AND cover.] Description [] @@ -156,20 +156,19 @@ char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ) SeeAlso [] ***********************************************************************/ -char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) +char * Abc_SopCreateAnd( 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' - (pfCompl? pfCompl[i] : 0); - pSop[nVars + 1] = '1'; + pSop[i] = '1'; return pSop; } /**Function************************************************************* - Synopsis [Creates the multi-input NAND cover.] + Synopsis [Starts the multi-input NAND cover.] Description [] @@ -191,7 +190,7 @@ char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars ) /**Function************************************************************* - Synopsis [Creates the multi-input OR cover.] + Synopsis [Starts the multi-input OR cover.] Description [] @@ -213,7 +212,7 @@ char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) /**Function************************************************************* - Synopsis [Creates the multi-input OR cover.] + Synopsis [Starts the multi-input OR cover.] Description [] @@ -238,7 +237,7 @@ char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl /**Function************************************************************* - Synopsis [Creates the multi-input NOR cover.] + Synopsis [Starts the multi-input NOR cover.] Description [] @@ -259,7 +258,7 @@ char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ) /**Function************************************************************* - Synopsis [Creates the multi-input XOR cover.] + Synopsis [Starts the multi-input XOR cover.] Description [] @@ -276,27 +275,7 @@ char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ) /**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.] + Synopsis [Starts the multi-input XNOR cover.] Description [] @@ -308,29 +287,12 @@ char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ) char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ) { assert( nVars == 2 ); - return Abc_SopRegister(pMan, "11 1\n00 1\n"); + return Abc_SopRegister(pMan, "11 1\n11 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.] + Synopsis [Starts the inv cover.] Description [] @@ -346,7 +308,7 @@ char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ) /**Function************************************************************* - Synopsis [Creates the buf cover.] + Synopsis [Starts the buf cover.] Description [] @@ -360,82 +322,6 @@ 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************************************************************* @@ -516,9 +402,9 @@ int Abc_SopGetVarNum( char * pSop ) int Abc_SopGetPhase( char * pSop ) { int nVars = Abc_SopGetVarNum( pSop ); - if ( pSop[nVars+1] == '0' || pSop[nVars+1] == 'n' ) + if ( pSop[nVars+1] == '0' ) return 0; - if ( pSop[nVars+1] == '1' || pSop[nVars+1] == 'x' ) + if ( pSop[nVars+1] == '1' ) return 1; assert( 0 ); return -1; @@ -567,10 +453,6 @@ void Abc_SopComplement( char * pSop ) *(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 ); } @@ -592,7 +474,7 @@ bool Abc_SopIsComplement( char * pSop ) char * pCur; for ( pCur = pSop; *pCur; pCur++ ) if ( *pCur == '\n' ) - return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n'); + return (int)(*(pCur - 1) == '0'); assert( 0 ); return 0; } @@ -723,27 +605,6 @@ bool Abc_SopIsOrType( char * pSop ) 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 [] @@ -768,8 +629,7 @@ bool Abc_SopCheck( char * pSop, int nFanins ) // 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 ); + fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover and its fanins.\n" ); return 0; } // check the output values for this cube @@ -778,9 +638,9 @@ bool Abc_SopCheck( char * pSop, int nFanins ) fFound0 = 1; else if ( *pCubes == '1' ) fFound1 = 1; - else if ( *pCubes != 'x' && *pCubes != 'n' ) + else { - fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes ); + fprintf( stdout, "Abc_SopCheck: SOP has a strange character in the output part of its cube.\n" ); return 0; } // check the last symbol (new line) @@ -799,274 +659,78 @@ bool Abc_SopCheck( char * pSop, int nFanins ) 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; + Synopsis [Writes the CNF of the SOP into file.] - // 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.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -char * Abc_SopFromTruthHex( char * pTruth ) +void Abc_SopWriteCnf( FILE * pFile, char * pClauses, Vec_Int_t * vVars ) { - 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 ) + char * pChar; + int i; + // check the logic function of the node + for ( pChar = pClauses; *pChar; pChar++ ) { - 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'; + // write the clause + for ( i = 0; i < vVars->nSize; i++, pChar++ ) + if ( *pChar == '0' ) + fprintf( pFile, "%d ", vVars->pArray[i] ); + else if ( *pChar == '1' ) + fprintf( pFile, "%d ", -vVars->pArray[i] ); + fprintf( pFile, "0\n" ); + // check that the remainig part is fine + assert( *pChar == ' ' ); + pChar++; + assert( *pChar == '1' ); + pChar++; + assert( *pChar == '\n' ); } - Vec_IntFree( vMints ); - return pSopCover; } /**Function************************************************************* - Synopsis [Creates one encoder node.] + Synopsis [Adds the clauses of for the CNF to the solver.] - 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.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues ) +void Abc_SopAddCnfToSolver( solver * pSat, char * pClauses, Vec_Int_t * vVars, Vec_Int_t * vTemp ) { - char * pResult; - Vec_Str_t * vSop; - int i, k; - assert( nValues > 1 ); - vSop = Vec_StrAlloc( 100 ); - for ( i = 0; i < nValues; i++ ) + char * pChar; + int i, RetValue; + // check the logic function of the node + for ( pChar = pClauses; *pChar; pChar++ ) { - 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' ); + // add the clause + vTemp->nSize = 0; + for ( i = 0; i < vVars->nSize; i++, pChar++ ) + if ( *pChar == '0' ) + Vec_IntPush( vTemp, toLit(vVars->pArray[i]) ); + else if ( *pChar == '1' ) + Vec_IntPush( vTemp, neg(toLit(vVars->pArray[i])) ); + // add the clause to the solver + RetValue = solver_addclause( pSat, vTemp->pArray, vTemp->pArray + vTemp->nSize ); + assert( RetValue != 1 ); + // check that the remainig part is fine + assert( *pChar == ' ' ); + pChar++; + assert( *pChar == '1' ); + pChar++; + assert( *pChar == '\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 index d3d32b98..7a6a705d 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -22,37 +22,17 @@ #include "main.h" #include "mio.h" #include "dec.h" -//#include "seq.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fFanouts, bool fReference ); + //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// -/**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.] @@ -68,7 +48,7 @@ void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; - if ( pNtk->nTravIds >= (1<<30)-1 ) + if ( pNtk->nTravIds == (1<<12)-1 ) { pNtk->nTravIds = 0; Abc_NtkForEachObj( pNtk, pObj, i ) @@ -77,49 +57,6 @@ void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ) 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.] @@ -138,8 +75,6 @@ int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ) assert( Abc_NtkHasSop(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { - if ( Abc_NodeIsConst(pNode) ) - continue; assert( pNode->pData ); nCubes += Abc_SopGetCubeNum( pNode->pData ); } @@ -156,33 +91,6 @@ int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ) 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 ) { @@ -245,36 +153,7 @@ int Abc_NtkGetBddNodeNum( Abc_Ntk_t * 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; + nNodes += pNode->pData? Cudd_DagSize( pNode->pData ) : 0; } return nNodes; } @@ -339,12 +218,7 @@ double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ) TotalArea = 0.0; Abc_NtkForEachNode( pNtk, pNode, i ) { -// assert( pNode->pData ); - if ( pNode->pData == NULL ) - { - printf( "Node without mapping is encountered.\n" ); - continue; - } + assert( pNode->pData ); TotalArea += Mio_GateReadArea( pNode->pData ); } return TotalArea; @@ -370,26 +244,6 @@ int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ) 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.] @@ -409,7 +263,7 @@ int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ) return 0; Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) - Counter += Abc_AigNodeIsChoice( pNode ); + Counter += Abc_NodeIsAigChoice( pNode ); return Counter; } @@ -436,26 +290,6 @@ int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ) 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.] @@ -471,74 +305,167 @@ void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; + i = 0; + // set the data filed to NULL Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pCopy = NULL; } /**Function************************************************************* - Synopsis [Cleans the copy field of all objects.] + Synopsis [Checks if the internal node has a unique CO.] - Description [] + Description [Checks if the internal node can borrow a name from a CO + fanout. This is possible if there is only one CO with non-complemented + fanin edge pointing to this node.] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkCleanData( Abc_Ntk_t * pNtk ) +Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ) { - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pData = NULL; + Abc_Obj_t * pFanout, * pFanoutCo; + int i, Counter; + if ( !Abc_ObjIsNode(pNode) ) + return NULL; + Counter = 0; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + if ( Abc_ObjIsCo(pFanout) && !Abc_ObjFaninC0(pFanout) ) + { + assert( Abc_ObjFaninNum(pFanout) == 1 ); + assert( Abc_ObjFanin0(pFanout) == pNode ); + pFanoutCo = pFanout; + Counter++; + } + } + if ( Counter == 1 ) + return pFanoutCo; + return NULL; } /**Function************************************************************* - Synopsis [Cleans the copy field of all objects.] + Synopsis [Returns 1 if COs of a logic network are simple.] - Description [] + Description [The COs of a logic network are simple under three conditions: + (1) The edge from CO to its driver is not complemented. + (2) No two COs share the same driver. + (3) The driver is not a CI unless the CI and the CO have the same name + (and so the inv/buf should not be written into a file).] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk ) +bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ) { - Abc_Obj_t * pObj; + Abc_Obj_t * pNode, * pDriver; int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pEquiv = NULL; + assert( !Abc_NtkIsNetlist(pNtk) ); + // check if there are complemented or idential POs + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + return 0; + if ( Abc_NodeIsTravIdCurrent(pDriver) ) + return 0; + if ( Abc_ObjIsCi(pDriver) && strcmp( Abc_ObjName(pDriver), Abc_ObjName(pNode) ) != 0 ) + return 0; + Abc_NodeSetTravIdCurrent(pDriver); + } + return 1; } /**Function************************************************************* - Synopsis [Counts the number of nodes having non-trivial copies.] + Synopsis [Transforms the network to have simple COs.] - Description [] + Description [The COs of a logic network are simple under three conditions: + (1) The edge from the CO to its driver is not complemented. + (2) No two COs share the same driver. + (3) The driver is not a CI unless the CI and the CO have the same name + (and so the inv/buf should not be written into a file). + 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_NtkCountCopy( Abc_Ntk_t * pNtk ) +int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate ) { - Abc_Obj_t * pObj; - int i, Counter = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_Obj_t * pNode, * pDriver, * pDriverNew, * pFanin; + int i, k, nDupGates = 0; + assert( Abc_NtkIsLogic(pNtk) ); + // process the COs by adding inverters and buffers when necessary + Abc_NtkForEachCo( pNtk, pNode, i ) { - if ( Abc_ObjIsNode(pObj) ) - Counter += (pObj->pCopy != NULL); + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsCi(pDriver) ) + { + // skip the case when the driver is a different node with the same name + if ( pDriver != pNode && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) == 0 ) + { + assert( !Abc_ObjFaninC0(pNode) ); + continue; + } + } + else + { + // skip the case when the driver's unique CO fanout is this CO + if ( Abc_NodeHasUniqueCoFanout(pDriver) == pNode ) + continue; + } + if ( fDuplicate && !Abc_ObjIsCi(pDriver) ) + { + pDriverNew = Abc_NtkDupObj( pNtk, pDriver ); + Abc_ObjForEachFanin( pDriver, pFanin, k ) + Abc_ObjAddFanin( pDriverNew, pFanin ); + if ( Abc_ObjFaninC0(pNode) ) + { + // change polarity of the duplicated driver + if ( Abc_NtkHasSop(pNtk) ) + Abc_SopComplement( pDriverNew->pData ); + else if ( Abc_NtkHasBdd(pNtk) ) + pDriverNew->pData = Cudd_Not( pDriverNew->pData ); + else + assert( 0 ); + Abc_ObjXorFaninC(pNode, 0); + } + } + else + { + // add inverters and buffers when necessary + if ( Abc_ObjFaninC0(pNode) ) + { + pDriverNew = Abc_NodeCreateInv( pNtk, pDriver ); + Abc_ObjXorFaninC( pNode, 0 ); + } + else + pDriverNew = Abc_NodeCreateBuf( pNtk, pDriver ); + } + // update the fanin of the PO node + Abc_ObjPatchFanin( pNode, pDriver, pDriverNew ); + assert( Abc_ObjFanoutNum(pDriverNew) == 1 ); + nDupGates++; + // remove the old driver if it dangles + if ( Abc_ObjFanoutNum(pDriver) == 0 ) + Abc_NtkDeleteObj( pDriver ); } - return Counter; + assert( Abc_NtkLogicHasSimpleCos(pNtk) ); + return nDupGates; } /**Function************************************************************* - Synopsis [Saves copy field of the objects.] + Synopsis [Inserts a new node in the order by levels.] Description [] @@ -547,20 +474,29 @@ int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ) +void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ) { - Vec_Ptr_t * vCopies; - Abc_Obj_t * pObj; + Abc_Obj_t * pNode1, * pNode2; int i; - vCopies = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachObj( pNtk, pObj, i ) - Vec_PtrWriteEntry( vCopies, i, pObj->pCopy ); - return vCopies; + 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 [Loads copy field of the objects.] + Synopsis [Returns 1 if the node is the root of EXOR/NEXOR.] Description [] @@ -569,17 +505,31 @@ Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ) +bool Abc_NodeIsExorType( Abc_Obj_t * pNode ) { - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pCopy = Vec_PtrEntry( vCopies, i ); + 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_NodeIsAigAnd(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 [Cleans the copy field of all objects.] + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] Description [] @@ -588,404 +538,45 @@ void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ) SeeAlso [] ***********************************************************************/ -void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ) +bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ) { - Abc_Obj_t * pObj; - int i = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pNext = NULL; + 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_NodeIsAigAnd(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 [Cleans the copy field of all objects.] + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - Description [] + 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 [] ***********************************************************************/ -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 * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ) { Abc_Obj_t * pNode0, * pNode1; assert( !Abc_ObjIsComplement(pNode) ); @@ -1082,7 +673,7 @@ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc { int fCheck = 1; FILE * pFile; - Abc_Ntk_t * pNtk1, * pNtk2, * pNtkTemp; + Abc_Ntk_t * pNtk1, * pNtk2; int util_optind = 0; *pfDelete1 = 0; @@ -1107,8 +698,15 @@ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc } else fclose( pFile ); - pNtk1 = pNtk; - pNtk2 = Io_Read( pNtk->pSpec, Io_ReadFileType(pNtk->pSpec), fCheck ); + + if ( Abc_NtkIsSeq(pNtk) ) + { + pNtk1 = Abc_NtkSeqToLogicSop(pNtk); + *pfDelete1 = 1; + } + else + pNtk1 = pNtk; + pNtk2 = Io_Read( pNtk->pSpec, fCheck ); if ( pNtk2 == NULL ) return 0; *pfDelete2 = 1; @@ -1120,18 +718,24 @@ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc fprintf( pErr, "Empty current network.\n" ); return 0; } - pNtk1 = pNtk; - pNtk2 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck ); + if ( Abc_NtkIsSeq(pNtk) ) + { + pNtk1 = Abc_NtkSeqToLogicSop(pNtk); + *pfDelete1 = 1; + } + else + pNtk1 = pNtk; + pNtk2 = Io_Read( 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 ); + pNtk1 = Io_Read( argv[util_optind], fCheck ); if ( pNtk1 == NULL ) return 0; - pNtk2 = Io_Read( argv[util_optind+1], Io_ReadFileType(argv[util_optind+1]), fCheck ); + pNtk2 = Io_Read( argv[util_optind+1], fCheck ); if ( pNtk2 == NULL ) { Abc_NtkDelete( pNtk1 ); @@ -1143,27 +747,8 @@ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc else { fprintf( pErr, "Wrong number of arguments.\n" ); - return 0; - } - - // make sure the networks are strashed - if ( !Abc_NtkIsStrash(pNtk1) ) - { - pNtkTemp = Abc_NtkStrash( pNtk1, 0, 1, 0 ); - if ( *pfDelete1 ) - Abc_NtkDelete( pNtk1 ); - pNtk1 = pNtkTemp; - *pfDelete1 = 1; - } - if ( !Abc_NtkIsStrash(pNtk2) ) - { - pNtkTemp = Abc_NtkStrash( pNtk2, 0, 1, 0 ); - if ( *pfDelete2 ) - Abc_NtkDelete( pNtk2 ); - pNtk2 = pNtkTemp; - *pfDelete2 = 1; + return 0; } - *ppNtk1 = pNtk1; *ppNtk2 = pNtk2; return 1; @@ -1185,7 +770,7 @@ void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; - Vec_PtrClear(vNodes); + vNodes->nSize = 0; Abc_ObjForEachFanin( pNode, pFanin, i ) Vec_PtrPush( vNodes, pFanin ); } @@ -1205,36 +790,14 @@ void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanout; int i; - Vec_PtrClear(vNodes); + vNodes->nSize = 0; 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.] + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] Description [] @@ -1320,461 +883,6 @@ Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ) 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 index 50558bdb..bef3836f 100644 --- a/src/base/abc/abc_.c +++ b/src/base/abc/abc_.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/base/abc/module.make b/src/base/abc/module.make index 7b34d8f6..649e71a2 100644 --- a/src/base/abc/module.make +++ b/src/base/abc/module.make @@ -1,12 +1,9 @@ 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 \ diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index a4f01217..e067a646 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -23,178 +23,81 @@ #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_CommandEliminate ( 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_CommandInter ( 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_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_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_CommandDRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFlowRetime ( 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_CommandSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDCec ( 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_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandIndcut ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandEnlarge ( 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 ); +static int Abc_CommandPrintStats ( 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_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_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowAig ( 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_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_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMiter ( 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_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOneOutput ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOneNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTest ( 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_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_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRetime ( 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_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -210,178 +113,78 @@ static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** arg ***********************************************************************/ 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, "Printing", "show_aig", Abc_CommandShowAig, 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", "eliminate", Abc_CommandEliminate, 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", "sat", Abc_CommandSat, 0 ); 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", "one_output", Abc_CommandOneOutput, 1 ); + Cmd_CommandAdd( pAbc, "Various", "one_node", Abc_CommandOneNode, 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", "inter", Abc_CommandInter, 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", "haig", Abc_CommandHaig, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "mini", Abc_CommandMini, 1 ); - 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", "seq", Abc_CommandSeq, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "dretime", Abc_CommandDRetime, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "fretime", Abc_CommandFlowRetime, 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, "Sequential", "sim", Abc_CommandSim, 0 ); Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 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", "iprove", Abc_CommandIProve, 1 ); - Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "bmc", Abc_CommandBmc, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "indcut", Abc_CommandIndcut, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "enlarge", Abc_CommandEnlarge, 1 ); - -// 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(); - + Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 ); { extern void Dar_LibStart(); Dar_LibStart(); } -} +} /**Function************************************************************* @@ -396,20 +199,16 @@ void Abc_Init( Abc_Frame_t * pAbc ) ***********************************************************************/ void Abc_End() { -// Dar_LibDumpPriorities(); - - { - extern void Cnf_ClearMemory(); - Cnf_ClearMemory(); - } + Abc_NtkFraigStoreClean(); +// Rwt_Man4ExplorePrint(); { extern void Dar_LibStop(); Dar_LibStop(); } - - Abc_NtkFraigStoreClean(); -// Rwt_Man4ExplorePrint(); - + { + extern void Cnf_ClearMemory(); + Cnf_ClearMemory(); + } } /**Function************************************************************* @@ -431,15 +230,15 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; int fFactor; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "sfh" ) ) != EOF ) { switch ( c ) { @@ -458,7 +257,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pNtk == NULL ) { - fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" ); + fprintf( Abc_FrameReadErr(pAbc), "Empty network\n" ); return 1; } Abc_NtkPrintStats( pOut, pNtk, fFactor ); @@ -466,104 +265,12 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: fprintf( pErr, "usage: print_stats [-fh]\n" ); - fprintf( pErr, "\t prints the network statistics\n" ); + fprintf( pErr, "\t prints the network statistics and\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 [] @@ -582,13 +289,13 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Obj_t * pNode; int c; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -605,18 +312,18 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc > globalUtilOptind + 1 ) + if ( argc > util_optind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == globalUtilOptind + 1 ) + if ( argc == util_optind + 1 ) { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); return 1; } Abc_NodePrintFanio( pOut, pNode ); @@ -651,13 +358,13 @@ int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk; int c; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -701,13 +408,13 @@ int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk; int c; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -735,58 +442,6 @@ usage: 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 [] @@ -806,14 +461,14 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; int fUseRealNames; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults fUseRealNames = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF ) { switch ( c ) { @@ -839,18 +494,18 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc > globalUtilOptind + 1 ) + if ( argc > util_optind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == globalUtilOptind + 1 ) + if ( argc == util_optind + 1 ) { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); return 1; } Abc_NodePrintFactor( pOut, pNode, fUseRealNames ); @@ -886,24 +541,19 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk; Abc_Obj_t * pNode; int c; - int fListNodes; int fProfile; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + fProfile = 1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ph" ) ) != EOF ) { switch ( c ) { - case 'n': - fListNodes ^= 1; - break; case 'p': fProfile ^= 1; break; @@ -926,31 +576,30 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc > globalUtilOptind + 1 ) + if ( argc > util_optind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == globalUtilOptind + 1 ) + if ( argc == util_optind + 1 ) { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); return 1; } Abc_NodePrintLevel( pOut, pNode ); return 0; } // process all COs - Abc_NtkPrintLevel( pOut, pNtk, fProfile, fListNodes ); + Abc_NtkPrintLevel( pOut, pNtk, fProfile ); return 0; usage: - fprintf( pErr, "usage: print_level [-nph] \n" ); + fprintf( pErr, "usage: print_level [-ph] \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"); @@ -974,26 +623,20 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) 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); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { - case 's': - fStruct ^= 1; - break; case 'v': fVerbose ^= 1; break; @@ -1009,17 +652,9 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) 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" ); + fprintf( pErr, "This command works only for combinational networks.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) @@ -1033,9 +668,8 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: print_supp [-svh]\n" ); + fprintf( pErr, "usage: print_supp [-vh]\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; @@ -1059,21 +693,19 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 ); + extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fVerbose ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "bnvh" ) ) != EOF ) { switch ( c ) { @@ -1083,9 +715,6 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'n': fNaive ^= 1; break; - case 'r': - fReorder ^= 1; - break; case 'v': fVerbose ^= 1; break; @@ -1102,25 +731,22 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( !Abc_NtkIsComb(pNtk) ) { - fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" ); + fprintf( pErr, "This command works only for combinational networks.\n" ); return 1; } - if ( Abc_NtkIsStrash(pNtk) ) - Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); - else + if ( !Abc_NtkIsStrash(pNtk) ) { - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); - Abc_NtkDelete( pNtk ); + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; } + Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fVerbose ); return 0; usage: - fprintf( pErr, "usage: print_symm [-bnrvh]\n" ); + fprintf( pErr, "usage: print_symm [-nbvh]\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-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; @@ -1137,64 +763,67 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; int c; - int fUseBdds; - int fUseNaive; - int fVerbose; - extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ); + extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != 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) ) + + if ( !Abc_NtkIsBddLogic(pNtk) ) { - fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks.\n" ); + return 1; + } + + if ( argc != util_optind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); return 1; } - Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose ); + Abc_NodeShowBdd( pNode ); 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"); + 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\n"); + fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -1209,45 +838,49 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv ) +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 Output; - int fNaive; - int fVerbose; - extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ); + int nNodeSizeMax; + int nConeSizeMax; + extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + nNodeSizeMax = 10; + nConeSizeMax = ABC_INFINITY; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "NCh" ) ) != EOF ) { switch ( c ) { - case 'O': - if ( globalUtilOptind >= argc ) + case 'N': + if ( util_optind >= argc ) { - fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } - Output = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( Output < 0 ) + nNodeSizeMax = atoi(argv[util_optind]); + util_optind++; + if ( nNodeSizeMax < 0 ) goto usage; break; - case 'n': - fNaive ^= 1; - break; - case 'v': - fVerbose ^= 1; + case 'C': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[util_optind]); + util_optind++; + if ( nConeSizeMax < 0 ) + goto usage; break; case 'h': goto usage; @@ -1255,27 +888,43 @@ int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv ) 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" ); + fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" ); return 1; } + if ( argc != util_optind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } - - Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose ); + pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + return 1; + } + Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); 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, "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; } @@ -1291,30 +940,23 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandShowAig( 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 ); + extern void Abc_NtkShowAig( Abc_Ntk_t * pNtk ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fUseRealNames = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { - case 'n': - fUseRealNames ^= 1; - break; case 'h': goto usage; default: @@ -1328,47 +970,26 @@ int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( !Abc_NtkIsLogic(pNtk) ) + if ( !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "Visualization of Karnaugh maps works for logic networks.\n" ); + fprintf( pErr, "Visualizing AIG can only be done for AIGs (run \"strash\").\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 ); + Abc_NtkShowAig( pNtk ); 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, "usage: show_aig [-h]\n" ); + fprintf( pErr, " visualizes the AIG with choices 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-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 [] @@ -1380,29 +1001,22 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkRes; int c; - int fUseLibrary; - - extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fUseLibrary = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { - case 'l': - fUseLibrary ^= 1; - break; case 'h': goto usage; default: @@ -1415,23 +1029,39 @@ int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( Abc_NtkHasAig(pNtk) ) + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "Printing gates does not work for AIGs and sequential AIGs.\n" ); + fprintf( pErr, "Can only collapse a logic network or an AIG.\n" ); return 1; } - Abc_NtkPrintGates( pNtk, fUseLibrary ); + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCollapse( pNtk, 1 ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0 ); + pNtkRes = Abc_NtkCollapse( pNtk, 1 ); + 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: 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, "usage: collapse [-h]\n" ); + fprintf( pErr, "\t collapses the network by constructing global BDDs\n" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } + /**Function************************************************************* Synopsis [] @@ -1443,28 +1073,31 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkRes; int c; - int fUseLibrary; - - extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ); + int fAllNodes; + int fCleanup; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fUseLibrary = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + fAllNodes = 0; + fCleanup = 1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ach" ) ) != EOF ) { switch ( c ) { - case 'l': - fUseLibrary ^= 1; + case 'a': + fAllNodes ^= 1; + break; + case 'c': + fCleanup ^= 1; break; case 'h': goto usage; @@ -1478,13 +1111,23 @@ int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - Abc_NtkPrintSharing( pNtk ); + + // get the new network + pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup ); + 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: 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, "usage: strash [-ach]\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-h : print the command usage\n"); return 1; } @@ -1500,28 +1143,26 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; int c; - int fUseLibrary; - - extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ); + int fDuplicate; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fUseLibrary = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + fDuplicate = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { - case 'l': - fUseLibrary ^= 1; + case 'd': + fDuplicate ^= 1; break; case 'h': goto usage; @@ -1535,13 +1176,38 @@ int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - Abc_NtkCrossCut( pNtk ); + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + { + pNtkRes = Abc_NtkBalance( pNtk, fDuplicate ); + } + else + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 ); + if ( pNtkTemp == NULL ) + { + fprintf( pErr, "Strashing before balancing has failed.\n" ); + return 1; + } + pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate ); + 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: 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, "usage: balance [-dh]\n" ); + fprintf( pErr, "\t transforms the current network into a well-balanced AIG\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; } @@ -1557,42 +1223,60 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRenode( 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 ); + Abc_Ntk_t * pNtk, * pNtkRes; + int nThresh, nFaninMax, c; + int fCnf; + int fMulti; + int fSimple; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + nThresh = 1; + nFaninMax = 20; + fCnf = 0; + fMulti = 0; + fSimple = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "TFmcsh" ) ) != EOF ) { switch ( c ) { - case 'N': - if ( globalUtilOptind >= argc ) + case 'T': + if ( util_optind >= argc ) { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nThresh = atoi(argv[util_optind]); + util_optind++; + if ( nThresh < 0 ) + goto usage; + break; + case 'F': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } - nCofLevel = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCofLevel < 0 ) + nFaninMax = atoi(argv[util_optind]); + util_optind++; + if ( nFaninMax < 0 ) goto usage; break; case 'c': - fCofactor ^= 1; + fCnf ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 's': + fSimple ^= 1; break; case 'h': goto usage; @@ -1606,51 +1290,38 @@ int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - // get the truth table of the first output - if ( !Abc_NtkIsLogic(pNtk) ) + if ( !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "Currently works only for logic networks.\n" ); + fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); return 1; } - Abc_NtkToAig( pNtk ); - // convert it to truth table + + // get the new network + pNtkRes = Abc_NtkRenode( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple ); + if ( pNtkRes == NULL ) { - 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 ); + fprintf( pErr, "Renoding has failed.\n" ); + return 1; } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); 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"); + fprintf( pErr, "usage: renode [-T num] [-F num] [-cmsh]\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 doing so prevents duplication of 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-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 [] @@ -1662,38 +1333,24 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandCleanup( 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); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { - case 'r': - fUseReverse ^= 1; - break; - case 's': - fSeq ^= 1; - break; - case 'g': - fGateNames ^= 1; - break; + case 'h': + goto usage; default: goto usage; } @@ -1704,20 +1361,18 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - - Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse ); + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cleanup cannot be performed on the AIG.\n" ); + return 1; + } + // modify the current network + Abc_NtkCleanup( pNtk, 0 ); 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, "usage: cleanup [-h]\n" ); + fprintf( pErr, "\t removes dangling nodes\n" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -1733,21 +1388,19 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandSweep( 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); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1763,51 +1416,23 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - - if ( !Abc_NtkIsBddLogic(pNtk) ) + if ( !Abc_NtkIsSopLogic(pNtk) && !Abc_NtkIsBddLogic(pNtk) ) { - fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" ); + fprintf( pErr, "Sweep cannot be performed on an AIG or a mapped network (unmap it first).\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 ); + // modify the current network + Abc_NtkSweep( pNtk, 0 ); 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, "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 [] @@ -1819,98 +1444,122 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) { - FILE * pOut, * pErr; Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; + FILE * pOut, * pErr; + Fxu_Data_t * p = NULL; int c; - int nNodeSizeMax; - int nConeSizeMax; - extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ); + extern bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); + extern void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + // allocate the structure + p = ALLOC( Fxu_Data_t, 1 ); + memset( p, 0, sizeof(Fxu_Data_t) ); + // set the defaults + p->nPairsMax = 30000; + p->nNodesExt = 10000; + p->fOnlyS = 0; + p->fOnlyD = 0; + p->fUse0 = 0; + p->fUseCompl = 1; + p->fVerbose = 0; + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "LNsdzcvh")) != EOF ) { - switch ( c ) + 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; + case 'L': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + p->nPairsMax = atoi(argv[util_optind]); + util_optind++; + if ( p->nPairsMax < 0 ) + goto usage; + break; + case 'N': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + p->nNodesExt = atoi(argv[util_optind]); + util_optind++; + 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_NtkIsStrash(pNtk) ) + if ( Abc_NtkNodeNum(pNtk) == 0 ) { - fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" ); + fprintf( pErr, "The network does not have internal nodes.\n" ); + Abc_NtkFxuFreeInfo( p ); return 1; } - if ( argc != globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) + if ( !Abc_NtkIsLogic(pNtk) ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + fprintf( pErr, "Fast extract can only be applied to a logic network (run \"renode\").\n" ); + Abc_NtkFxuFreeInfo( p ); return 1; } - Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); + + + // 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: 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, "usage: fx [-N num] [-L num] [-sdzcvh]\n"); + fprintf( pErr, "\t performs unate fast extract on the current network\n"); + fprintf( pErr, "\t-N num : the maximum number of divisors to extract [default = %d]\n", p->nNodesExt ); + fprintf( pErr, "\t-L num : the maximum number of cube pairs to consider [default = %d]\n", p->nPairsMax ); + 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"); - return 1; + Abc_NtkFxuFreeInfo( p ); + return 1; } - /**Function************************************************************* Synopsis [] @@ -1922,54 +1571,50 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandDisjoint( 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; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkNew; + int fGlobal, fRecursive, fVerbose, fPrint, fShort, c; - pNtk = Abc_FrameReadNtk(pAbc); + 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_FrameReadNet(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 ) + fGlobal = 1; + fRecursive = 0; + fVerbose = 0; + fPrint = 0; + fShort = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "grvpsh" ) ) != EOF ) { switch ( c ) { - case 'B': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); + 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; - } - fBddSizeMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( fBddSizeMax < 0 ) + break; + default: 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; } } @@ -1979,42 +1624,64 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + if ( fGlobal ) { - fprintf( pErr, "Can only collapse a logic network or an AIG.\n" ); - return 1; +// 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 ); + 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 ); } - - // get the new network - if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); - else + else if ( fRecursive ) { - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); - Abc_NtkDelete( pNtk ); + 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" ); } - if ( pNtkRes == NULL ) + else { - fprintf( pErr, "Collapsing has failed.\n" ); - return 1; + if ( !Abc_NtkIsBddLogic( pNtk ) ) + { + fprintf( pErr, "This command is only applicable to logic BDD networks.\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" ); } - // 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"); + 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 [] @@ -2026,36 +1693,39 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Ntk_t * pNtk; int c; - int fAllNodes; - int fRecord; - int fCleanup; + bool fPrecompute; + bool fUseZeros; + bool fVerbose; + // external functions + extern void Rwr_Precompute(); + extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUseZeros, int fVerbose ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + fPrecompute = 0; + fUseZeros = 0; + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "xzvh" ) ) != EOF ) { switch ( c ) { - case 'a': - fAllNodes ^= 1; + case 'x': + fPrecompute ^= 1; break; - case 'c': - fCleanup ^= 1; + case 'z': + fUseZeros ^= 1; break; - case 'r': - fRecord ^= 1; + case 'v': + fVerbose ^= 1; break; case 'h': goto usage; @@ -2064,30 +1734,42 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) } } + 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; + } - // get the new network - pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord ); - if ( pNtkRes == NULL ) + // modify the current network + if ( !Abc_NtkRewrite( pNtk, fUseZeros, fVerbose ) ) { - fprintf( pErr, "Strashing has failed.\n" ); + fprintf( pErr, "Rewriting 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"); + fprintf( pErr, "usage: rewrite [-zvh]\n" ); + fprintf( pErr, "\t performs technology-independent rewriting of the AIG\n" ); + 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; } @@ -2102,36 +1784,63 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; + Abc_Ntk_t * pNtk; int c; - bool fDuplicate; - bool fSelective; - bool fUpdateLevel; + int nNodeSizeMax; + int nConeSizeMax; + bool fUseZeros; + bool fUseDcs; + bool fVerbose; + extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseZeros, bool fUseDcs, bool fVerbose ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + nNodeSizeMax = 10; + nConeSizeMax = 16; + fUseZeros = 0; + fUseDcs = 0; + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "NCzdvh" ) ) != EOF ) { switch ( c ) { - case 'l': - fUpdateLevel ^= 1; + case 'N': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[util_optind]); + util_optind++; + if ( nNodeSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[util_optind]); + util_optind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'z': + fUseZeros ^= 1; break; case 'd': - fDuplicate ^= 1; + fUseDcs ^= 1; break; - case 's': - fSelective ^= 1; + case 'v': + fVerbose ^= 1; break; case 'h': goto usage; @@ -2145,43 +1854,44 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - // get the new network - if ( Abc_NtkIsStrash(pNtk) ) + if ( !Abc_NtkIsStrash(pNtk) ) { - pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel ); + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; } - else + if ( Abc_NtkGetChoiceNum(pNtk) ) { - 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 ); + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; } - // check if balancing worked - if ( pNtkRes == NULL ) + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) { - fprintf( pErr, "Balancing has failed.\n" ); + 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, fUseZeros, fUseDcs, fVerbose ) ) + { + fprintf( pErr, "Refactoring 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"); + fprintf( pErr, "usage: refactor [-N num] [-C num] [-zdvh]\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-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 [] @@ -2193,67 +1903,22 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandLogic( 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 ); + int c; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != 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: @@ -2266,17 +1931,18 @@ int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsStrash(pNtk) ) + + if ( !Abc_NtkIsNetlist( pNtk ) ) { - fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); + fprintf( pErr, "This command is only applicable to netlists.\n" ); return 1; } // get the new network - pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor ); + pNtkRes = Abc_NtkNetlistToLogic( pNtk ); if ( pNtkRes == NULL ) { - fprintf( pErr, "Renoding has failed.\n" ); + fprintf( pErr, "Converting to a logic network has failed.\n" ); return 1; } // replace the current network @@ -2284,18 +1950,9 @@ int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv ) 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"); + fprintf( pErr, "usage: logic [-h]\n" ); + fprintf( pErr, "\t transforms a netlist into a logic network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -2310,143 +1967,51 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandMiter( 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 ); + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fCheck; + int fComb; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + fComb = 1; + fCheck = 1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != 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; + fComb ^= 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" ); + pArgvNew = argv + util_optind; + nArgcNew = argc - util_optind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) 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; - } + // compute the miter + pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb ); + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); // 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" ); + fprintf( pErr, "Miter computation has failed.\n" ); return 1; } // replace the current network @@ -2454,20 +2019,14 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv ) 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"); + fprintf( pErr, "usage: miter [-ch] \n" ); + fprintf( pErr, "\t computes the miter of the two circuits\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, "\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; } @@ -2482,22 +2041,40 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes; + int fInitial; + int nFrames; int c; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + fInitial = 0; + nFrames = 5; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "Fih" ) ) != EOF ) { switch ( c ) { + case 'F': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[util_optind]); + util_optind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'i': + fInitial ^= 1; + break; case 'h': goto usage; default: @@ -2510,22 +2087,35 @@ int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( Abc_NtkIsStrash(pNtk) ) + + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "Cleanup cannot be performed on the AIG.\n" ); + pNtkTemp = Abc_NtkStrash( pNtk, 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; } - // modify the current network - Abc_NtkCleanup( pNtk, 1 ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); 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"); + 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 [] @@ -2537,19 +2127,19 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk; int c; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -2565,23 +2155,27 @@ int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsLogic(pNtk) ) + + // get the new network + if ( !Abc_NtkIsBddLogic(pNtk) ) { - fprintf( pErr, "The classical (SIS-like) sweep can only be performed on a logic network.\n" ); + fprintf( pErr, "Converting to SOP is possible when node functions are BDDs.\n" ); + return 1; + } + if ( !Abc_NtkBddToSop( pNtk ) ) + { + fprintf( pErr, "Converting to SOP has failed.\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"); + fprintf( pErr, "usage: sop [-h]\n" ); + fprintf( pErr, "\t converts node functions from BDD to SOP\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); return 1; } - /**Function************************************************************* Synopsis [] @@ -2593,133 +2187,53 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; FILE * pOut, * pErr; - Fxu_Data_t * p = NULL; + Abc_Ntk_t * pNtk; 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); + pNtk = Abc_FrameReadNet(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 ) + // set defaults + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { - switch (c) + 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; + case 'h': + goto usage; + default: + goto usage; } - } + } if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); - Abc_NtkFxuFreeInfo( p ); return 1; } - if ( Abc_NtkNodeNum(pNtk) == 0 ) + // get the new network + if ( !Abc_NtkIsSopLogic(pNtk) ) { - fprintf( pErr, "The network does not have internal nodes.\n" ); - Abc_NtkFxuFreeInfo( p ); + fprintf( pErr, "Converting to BDD is possible when node functions are SOPs.\n" ); return 1; } - - if ( !Abc_NtkIsLogic(pNtk) ) + if ( !Abc_NtkSopToBdd( pNtk ) ) { - fprintf( pErr, "Fast extract can only be applied to a logic network (run \"renode\").\n" ); - Abc_NtkFxuFreeInfo( p ); + fprintf( pErr, "Converting to BDD has failed.\n" ); 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, "usage: bdd [-h]\n" ); + fprintf( pErr, "\t converts node functions from SOP to BDD\n" ); fprintf( pErr, "\t-h : print the command usage\n"); - Abc_NtkFxuFreeInfo( p ); - return 1; + return 1; } /**Function************************************************************* @@ -2733,53 +2247,28 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandEliminate( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; FILE * pOut, * pErr; - int nMaxSize; - int fReverse; - int fVerbose; + Abc_Ntk_t * pNtk, * pNtkRes; int c; - extern int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); - // set the defaults - nMaxSize = 8; - fReverse = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "Nrvh")) != EOF ) + // set defaults + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { - switch (c) + switch ( c ) { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by a positive integer.\n" ); - goto usage; - } - nMaxSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nMaxSize <= 0 ) - goto usage; - break; - case 'r': - fReverse ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; + case 'h': + goto usage; + default: + goto usage; } - } + } if ( pNtk == NULL ) { @@ -2787,30 +2276,29 @@ int Abc_CommandEliminate( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( Abc_NtkNodeNum(pNtk) == 0 ) + if ( !Abc_NtkIsBddLogic(pNtk) ) { - fprintf( pErr, "The network does not have internal nodes.\n" ); + fprintf( pErr, "Only a BDD logic network can be converted to MUXes.\n" ); return 1; } - if ( !Abc_NtkIsLogic(pNtk) ) + // get the new network + pNtkRes = Abc_NtkBddToMuxes( pNtk ); + if ( pNtkRes == NULL ) { - fprintf( pErr, "This command can only be applied to a logic network (run \"renode\" or \"if\").\n" ); + fprintf( pErr, "Converting to MUXes has failed.\n" ); return 1; } - - // the nodes to be merged are linked into the special linked list - Abc_NtkEliminate( pNtk, nMaxSize, fReverse, fVerbose ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: - fprintf( pErr, "usage: eliminate [-N num] [-rvh]\n"); - fprintf( pErr, "\t greedily eliminates nodes by collapsing them into fanouts\n"); - fprintf( pErr, "\t-N num : the maximum support size after collapsing [default = %d]\n", nMaxSize ); - fprintf( pErr, "\t-r : use the reverse topological order [default = %s]\n", fReverse? "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; + 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************************************************************* @@ -2824,50 +2312,31 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandSat( 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 ); + Abc_Ntk_t * pNtk; + int c; + int fVerbose; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "vh" ) ) != 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; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; } } @@ -2876,65 +2345,36 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) 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_NtkLatchNum(pNtk) > 0 ) { - 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" ); + fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); + return 0; } - else + if ( !Abc_NtkIsLogic(pNtk) ) { - 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" ); + fprintf( stdout, "This command can only be applied to logic network (run \"renode -c\").\n" ); + return 0; } + if ( Abc_NtkIsMappedLogic(pNtk) ) + Abc_NtkUnmap(pNtk); + if ( Abc_NtkIsSopLogic(pNtk) ) + Abc_NtkSopToBdd(pNtk); + + if ( Abc_NtkMiterSat( pNtk, fVerbose ) ) + printf( "The miter is satisfiable.\n" ); + else + printf( "The miter is unsatisfiable.\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, "usage: sat [-vh]\n" ); + fprintf( pErr, "\t solves the miter\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 [] @@ -2946,85 +2386,27 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk; - Res_Par_t Pars, * pPars = &Pars; int c; + int fVerbose; + extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, bool fVerbose ); -// printf( "Implementation of this command is not finished.\n" ); -// return 1; - - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - pPars->nWindow = 62; - pPars->nCands = 5; - pPars->nSimWords = 4; - pPars->nGrowthLevel = 0; - pPars->fArea = 0; - pPars->fVerbose = 0; - pPars->fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF ) + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "vh" ) ) != 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; + case 'v': + fVerbose ^= 1; break; case 'h': goto usage; @@ -3038,34 +2420,30 @@ int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsLogic(pNtk) ) + if ( Abc_NtkLatchNum(pNtk) == 0 ) { - fprintf( pErr, "This command can only be applied to a logic network.\n" ); - return 1; + fprintf( stdout, "The current network has no latches.\n" ); + return 0; } - - // modify the current network - if ( !Abc_NtkResynthesize( pNtk, pPars ) ) + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "This command works only for AIGs (run \"strash\").\n" ); + return 0; + } + if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) ) { - fprintf( pErr, "Resynthesis has failed.\n" ); + fprintf( stdout, "Extracting sequential don't-cares 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 (there is another command for resynthesis after LUT mapping, \"lutpack\")\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-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-L : the largest increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); - 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"); + 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************************************************************* @@ -3078,95 +2456,40 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Lpk_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pNode; int c; - - pNtk = Abc_FrameReadNtk(pAbc); + int fUseAllCis; + int Output; + + pNtk = Abc_FrameReadNet(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 ) + fUseAllCis = 0; + Output = -1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "Oah" ) ) != 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 ) + case 'O': + if ( util_optind >= argc ) { - fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } - pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) + Output = atoi(argv[util_optind]); + util_optind++; + if ( Output < 0 ) 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; + case 'a': + fUseAllCis ^= 1; break; case 'h': goto usage; @@ -3180,45 +2503,61 @@ int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsLogic(pNtk) ) + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "This command can only be applied to a logic network.\n" ); + fprintf( pErr, "Currently can only be applied to the logic network or an AIG.\n" ); return 1; } - if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 ) + + if ( argc > util_optind + 1 ) { - fprintf( pErr, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared ); - return 1; + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; } - // modify the current network - if ( !Lpk_Resynthesize( pNtk, pPars ) ) + if ( argc == util_optind + 1 ) + { + pNode = Abc_NtkFindCo( pNtk, argv[util_optind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find CO node \"%s\".\n", argv[util_optind] ); + return 1; + } + pNtkRes = Abc_NtkSplitOutput( pNtk, pNode, fUseAllCis ); + } + else + { + if ( Output == -1 ) + { + fprintf( pErr, "The output 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; + } + pNtkRes = Abc_NtkSplitOutput( pNtk, Abc_NtkCo(pNtk,Output), fUseAllCis ); + } + if ( pNtkRes == NULL ) { - fprintf( pErr, "Resynthesis has failed.\n" ); + fprintf( pErr, "Splitting one output has failed.\n" ); return 1; } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); 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 determines LUT size as the max fanin count of a node;\n" ); - fprintf( pErr, "\t if the network is not LUT-mapped, packs it into 6-LUTs\n" ); - fprintf( pErr, "\t (there is another command for resynthesis after LUT mapping, \"imfs\")\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"); + fprintf( pErr, "usage: one_output [-O num] [-ah] \n" ); + fprintf( pErr, "\t replaces the current network by the logic cone of one output\n" ); + fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t-O num : (optional) the 0-based number of the output\n"); + fprintf( pErr, "\tname : (optional) the name of the output\n"); return 1; -} - +} /**Function************************************************************* @@ -3231,102 +2570,75 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pNode; int c; - bool fUpdateLevel; - bool fPrecompute; - bool fUseZeros; - bool fVerbose; - bool fVeryVerbose; - bool fPlaceEnable; - // external functions - extern void Rwr_Precompute(); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != 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': + 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) ) + + if ( !Abc_NtkIsLogic(pNtk) ) { - fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + fprintf( pErr, "Currently can only be applied to a logic network.\n" ); return 1; } - if ( Abc_NtkGetChoiceNum(pNtk) ) + + if ( argc != util_optind + 1 ) { - fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); return 1; } - // modify the current network - if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) ) + pNtkRes = Abc_NtkSplitNode( pNtk, pNode ); +// pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL ); + if ( pNtkRes == NULL ) { - fprintf( pErr, "Rewriting has failed.\n" ); + fprintf( pErr, "Splitting one node has failed.\n" ); return 1; } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); 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, "usage: one_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************************************************************* @@ -3339,69 +2651,22 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandShortNames( 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); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != 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: @@ -3414,40 +2679,12 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; - } + Abc_NtkShortNames( pNtk ); 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, "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; } @@ -3463,50 +2700,72 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandCut( 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; - int nCutsMax; - bool fUpdateLevel; - bool fUseZeros; - bool fVerbose; - extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); + extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + pParams->nVarsMax = 5; // 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->fHash = 0; // hash cuts to detect unique + pParams->fFilter = 0; // filter dominated cuts + pParams->fSeq = 0; // compute sequential cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fVerbose = 0; // the verbosiness flag + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "KMtrfsdvh" ) ) != EOF ) { switch ( c ) { case 'K': - if ( globalUtilOptind >= argc ) + if ( util_optind >= argc ) { fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } - nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCutsMax < 0 ) + pParams->nVarsMax = atoi(argv[util_optind]); + util_optind++; + if ( pParams->nVarsMax < 0 ) goto usage; break; - case 'l': - fUpdateLevel ^= 1; + case 'M': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nKeepMax = atoi(argv[util_optind]); + util_optind++; + if ( pParams->nKeepMax < 0 ) + goto usage; break; - case 'z': - fUseZeros ^= 1; + case 't': + pParams->fTruth ^= 1; + break; + case 'r': + pParams->fHash ^= 1; + break; + case 'f': + pParams->fFilter ^= 1; + break; + case 's': + pParams->fSeq ^= 1; + break; + case 'd': + pParams->fDrop ^= 1; break; case 'v': - fVerbose ^= 1; + pParams->fVerbose ^= 1; break; case 'h': goto usage; @@ -3520,37 +2779,27 @@ int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv ) 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" ); + fprintf( pErr, "Cut computation is available only for AIGs (run \"strash\").\n" ); return 1; } + pCutMan = Abc_NtkCuts( pNtk, pParams ); + Cut_ManPrintStats( pCutMan ); + Cut_ManStop( pCutMan ); 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, "usage: cut [-K num] [-M num] [-trfsdvh]\n" ); + fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" ); + fprintf( pErr, "\t-K num : max number of leaves (4 <= num <= 6) [default = %d]\n", 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-r : toggle reduction by hashing [default = %s]\n", pParams->fHash? "yes": "no" ); + fprintf( pErr, "\t-f : toggle filtering by dominance [default = %s]\n", pParams->fFilter? "yes": "no" ); + fprintf( pErr, "\t-s : toggle sequential cut computation [default = %s]\n", pParams->fSeq? "yes": "no" ); + fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "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; } @@ -3566,139 +2815,54 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandTest( 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; + Abc_Ntk_t * pNtk, * pNtkRes; 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); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != 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 ) ) + // run the command + pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 ); + if ( pNtkRes == NULL ) { - fprintf( pErr, "Refactoring has failed.\n" ); + fprintf( pErr, "Command has failed.\n" ); return 1; } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); 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, "usage: test [-h]\n" ); + fprintf( pErr, "\t testbench for new procedures\n" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } + + + /**Function************************************************************* Synopsis [] @@ -3710,87 +2874,146 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv ) +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; - 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 ); + Abc_Ntk_t * pNtk, * pNtkRes; + int fAllNodes; + int c; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + fAllNodes = 0; + pParams->nPatsRand = 2048; // the number of words of random simulation info + pParams->nPatsDyna = 2048; // the number of words of dynamic simulation info + pParams->nBTLimit = 99; // 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 = 0; // 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 + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "RDBrscpvah" ) ) != EOF ) { switch ( c ) { - case 'W': - if ( globalUtilOptind >= argc ) + + case 'R': + if ( util_optind >= argc ) { - fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } - Window = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( Window < 0 ) + pParams->nPatsRand = atoi(argv[util_optind]); + util_optind++; + if ( pParams->nPatsRand < 0 ) goto usage; - nFaninLevels = Window / 10; - nFanoutLevels = Window % 10; break; - case 'f': - fUseFanouts ^= 1; + case 'D': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nPatsDyna = atoi(argv[util_optind]); + util_optind++; + if ( pParams->nPatsDyna < 0 ) + goto usage; + break; + case 'B': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nBTLimit = atoi(argv[util_optind]); + util_optind++; + 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': - fVerbose ^= 1; + pParams->fVerbose ^= 1; + break; + case 'a': + fAllNodes ^= 1; break; case 'h': goto usage; default: goto usage; } - } + } if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsStrash(pNtk) ) + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + fprintf( pErr, "Can only fraig a logic network or an AIG.\n" ); return 1; } - if ( Abc_NtkGetChoiceNum(pNtk) ) + + // report the proof + pParams->fVerboseP = pParams->fTryProve; + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes ); + else { - fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); - return 1; + pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes ); + pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes ); + Abc_NtkDelete( pNtk ); } - - // modify the current network - if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) ) + if ( pNtkRes == NULL ) { - fprintf( pErr, "Redundancy removal has failed.\n" ); + 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: - 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" ); + sprintf( Buffer, "%d", pParams->nBTLimit ); + fprintf( pErr, "usage: fraig [-R num] [-D num] [-B num] [-rscpvah]\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-B 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 final miter [default = %s]\n", pParams->fTryProve? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-a : toggle between all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "dfs" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -3806,44 +3029,26 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandFraigTrust( 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 ); + int c; + int fDuplicate; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + fDuplicate = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "dh" ) ) != 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; + case 'd': + fDuplicate ^= 1; break; case 'h': goto usage; @@ -3858,24 +3063,11 @@ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 ); - } + pNtkRes = Abc_NtkFraigTrust( pNtk ); if ( pNtkRes == NULL ) { - fprintf( pErr, "Cascade synthesis has failed.\n" ); + fprintf( pErr, "Fraiging in the trust mode has failed.\n" ); return 1; } // replace the current network @@ -3883,22 +3075,13 @@ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) 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"); + 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 [] @@ -3910,22 +3093,27 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Ntk_t * pNtk; int c; + int fDuplicate; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + fDuplicate = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { + case 'd': + fDuplicate ^= 1; + break; case 'h': goto usage; default: @@ -3939,26 +3127,18 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( !Abc_NtkIsStrash( pNtk ) ) + // get the new network + if ( !Abc_NtkFraigStore( pNtk ) ) { - fprintf( pErr, "This command is only applicable to strashed networks.\n" ); + fprintf( pErr, "Fraig storing has failed.\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; + return 0; usage: - fprintf( pErr, "usage: logic [-h]\n" ); - fprintf( pErr, "\t transforms an AIG into a logic network with SOPs\n" ); + 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; } @@ -3974,22 +3154,27 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv ) +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); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + fDuplicate = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { + case 'd': + fDuplicate ^= 1; + break; case 'h': goto usage; default: @@ -4002,96 +3187,12 @@ int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 + pNtkRes = Abc_NtkFraigRestore(); if ( pNtkRes == NULL ) { - fprintf( pErr, "Miter computation has failed.\n" ); + fprintf( pErr, "Fraig restoring has failed.\n" ); return 1; } // replace the current network @@ -4099,19 +3200,10 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) 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"); + 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; } @@ -4126,64 +3218,40 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk;//, * pNtkRes; - int fComb; + Abc_Ntk_t * pNtk; int c; - extern int Abc_NtkDemiter( Abc_Ntk_t * pNtk ); + int fDuplicate; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + fDuplicate = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { - case 'c': - fComb ^= 1; + case 'd': + fDuplicate ^= 1; break; + case 'h': + goto usage; 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 ); + Abc_NtkFraigStoreClean(); 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, "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; } @@ -4199,69 +3267,72 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk;//, * pNtkRes; - int fComb; + Abc_Ntk_t * pNtk; int c; - extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); + int fUseInv; + int fVerbose; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + fUseInv = 1; + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ivh" ) ) != EOF ) { switch ( c ) { - case 'c': - fComb ^= 1; + case 'i': + fUseInv ^= 1; break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; default: goto usage; } } - if ( !Abc_NtkIsStrash(pNtk) ) + if ( pNtk == NULL ) { - fprintf( pErr, "The network is not strashed.\n" ); + fprintf( pErr, "Empty network.\n" ); return 1; } -/* - if ( Abc_NtkPoNum(pNtk) == 1 ) + if ( Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "The network already has one PO.\n" ); + fprintf( pErr, "Cannot sweep AIGs (use \"fraig\").\n" ); return 1; } -*/ -/* - if ( Abc_NtkLatchNum(pNtk) ) + if ( !Abc_NtkIsLogic(pNtk) ) { - fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); + fprintf( pErr, "Transform the current network into a logic network.\n" ); return 1; } -*/ - // get the new network - if ( !Abc_NtkCombinePos( pNtk, 0 ) ) + // modify the current network + if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fVerbose ) ) { - fprintf( pErr, "ORing the POs has failed.\n" ); + fprintf( pErr, "Sweeping 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, "usage: fraig_sweep [-vh]\n" ); + fprintf( pErr, "\t performs technology-dependent sweep\n" ); +// fprintf( pErr, "\t-i : toggle using inverter for complemented nodes [default = %s]\n", fUseInv? "yes": "no" ); + 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 [] @@ -4273,8342 +3344,131 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk;//, * pNtkRes; - int fComb; + Abc_Ntk_t * pNtk, * pNtkRes; + char Buffer[100]; + double DelayTarget; + int fRecovery; + int fSweep; + int fSwitching; + int fVerbose; int c; - extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); + extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + DelayTarget =-1; + fRecovery = 1; + fSweep = 1; + fSwitching = 0; + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "Daspvh" ) ) != EOF ) { switch ( c ) { - case 'c': - fComb ^= 1; + case 'D': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayTarget = (float)atof(argv[util_optind]); + util_optind++; + 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 ( !Abc_NtkIsStrash(pNtk) ) + if ( pNtk == NULL ) { - fprintf( pErr, "The network is not strashed.\n" ); + fprintf( pErr, "Empty network.\n" ); return 1; } - if ( Abc_NtkPoNum(pNtk) == 1 ) + if ( !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "The network already has one PO.\n" ); - return 1; + pNtk = Abc_NtkStrash( pNtk, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0 ); + 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 ); } - - if ( Abc_NtkLatchNum(pNtk) ) + else { - fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); - return 1; + // get the new network + pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Mapping has failed.\n" ); + return 1; + } } - // get the new network - if ( !Abc_NtkCombinePos( pNtk, 1 ) ) - { - fprintf( pErr, "ANDing the POs has failed.\n" ); - return 1; - } + if ( fSweep ) + Abc_NtkFraigSweep( pNtkRes, 0, 0 ); + // replace the current network -// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + 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_CommandInter( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes, * pNtk1, * pNtk2; - char ** pArgvNew; - int nArgcNew; - int c, fDelete1, fDelete2; - int fVerbose; - extern Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, 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; - } - } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) - return 1; - if ( nArgcNew == 0 ) - { - printf( "Deriving new circuit structure for the current network.\n" ); - Abc_ObjXorFaninC( Abc_NtkPo(pNtk2,0), 0 ); - } - pNtkRes = Abc_NtkInter( pNtk1, pNtk2, fVerbose ); - if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); - if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); - - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: inter [-vh] \n" ); - fprintf( pErr, "\t derives interpolant of two networks (onset and offset)\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_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 fBmc; - int nFrames; - int nLevels; - int fVerbose; - int fVeryVerbose; -// 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 ); - extern Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk ); - extern void Abc_NtkDarTestBlif( char * pFileName ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - printf( "This command is temporarily disabled.\n" ); - return 0; - - // set defaults - fVeryVerbose = 0; - fVerbose = 1; - fBmc = 1; - nFrames = 1; - nLevels = 200; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FNbvwh" ) ) != 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 '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 'b': - fBmc ^= 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_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 ); -*/ - -// Abc_NtkDarHaigRecord( pNtk ); -// Abc_NtkDarClau( pNtk, nFrames, nLevels, fBmc, fVerbose, fVeryVerbose ); - - if ( globalUtilOptind != 1 ) - { - fprintf( pErr, "Command has failed.\n" ); - return 1; - } - Abc_NtkDarTestBlif( argv[globalUtilOptind] ); - - return 0; -usage: - fprintf( pErr, "usage: test [-vwh]\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-w : toggle printing very verbose 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_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_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 (there are also newer fraiging commands, \"ifraig\" and \"dfraig\")\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->fEdge = 0; - pPars->fCutMin = 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, "KCFADpaflemrstvh" ) ) != 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 'r': - pPars->fExpRed ^= 1; - break; - case 'f': - pPars->fFancy ^= 1; - break; - case 'l': - pPars->fLatchPaths ^= 1; - break; - case 'e': - pPars->fEdge ^= 1; - break; - case 'm': - pPars->fCutMin ^= 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; - } - - // enable truth table computation if choices are selected - if ( Abc_NtkGetChoiceNum( pNtk ) ) - { - printf( "Performing FPGA mapping with choices.\n" ); - pPars->fTruth = 1; - } - // enable truth table computation if cut minimization is selected - if ( pPars->fCutMin ) - pPars->fTruth = 1; - - // complain if truth tables are requested but the cut size is too large - if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE ) - { - fprintf( pErr, "Truth tables cannot be computed for LUT larger than %d inputs.\n", IF_MAX_FUNC_LUTSIZE ); - return 1; - } - - // disable cut-expansion if edge-based heuristics are selected -// if ( pPars->fEdge ) -// pPars->fExpRed = 0; - - 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] [-parlemsvh]\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-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" ); - fprintf( pErr, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "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 ) - { - srand( time(NULL) ); - 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_CommandDRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int nStepsMax; - int fFastAlgo; - int fVerbose; - int c; - extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ); - extern Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nStepsMax = 100000; - fFastAlgo = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Savh" ) ) != EOF ) - { - switch ( c ) - { - case 'S': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-S\" should be followed by a positive integer.\n" ); - goto usage; - } - nStepsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nStepsMax < 0 ) - goto usage; - break; - case 'a': - fFastAlgo ^= 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) ) - { - fprintf( pErr, "The network has no latches. Retiming is not performed.\n" ); - return 0; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); - return 0; - } - - // perform the retiming - if ( fFastAlgo ) - pNtkRes = Abc_NtkDarRetime( pNtk, nStepsMax, fVerbose ); - else - pNtkRes = Abc_NtkDarRetimeF( pNtk, nStepsMax, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Retiming has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: dretime [-S num] [-avh]\n" ); - fprintf( pErr, "\t retimes the current network forward\n" ); - fprintf( pErr, "\t-S num : the max number of retiming steps to perform [default = %d]\n", nStepsMax ); - fprintf( pErr, "\t-a : enables a fast algorithm [default = %s]\n", fFastAlgo? "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; -} -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, nMaxIters; - int fForward; - int fBackward; - int fVerbose; - int fComputeInit; - int maxDelay; - - extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInit, - int fForward, int fBackward, int nMaxIters, - int maxDelay); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fForward = 0; - fBackward = 0; - fComputeInit = 1; - fVerbose = 0; - nMaxIters = 999; - maxDelay = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "MDfbivh" ) ) != EOF ) - { - switch ( c ) - { - case 'M': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" ); - goto usage; - } - nMaxIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nMaxIters < 0 ) - goto usage; - break; - case 'D': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-D\" should be followed by a positive integer.\n" ); - goto usage; - } - maxDelay = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( maxDelay < 0 ) - goto usage; - break; - case 'f': - fForward ^= 1; - break; - case 'i': - fComputeInit ^= 1; - break; - case 'b': - fBackward ^= 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 ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "Retiming with choice nodes is not implemented.\n" ); - return 0; - } - - // perform the retiming - pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit, fForward, fBackward, nMaxIters, maxDelay ); - - if (pNtkRes != pNtk) - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - - return 0; - -usage: - fprintf( pErr, "usage: fretime [-M num] [-D num] [-fbvih]\n" ); - fprintf( pErr, "\t retimes the current network using flow-based algorithm\n" ); - fprintf( pErr, "\t-M num : the maximum number of iterations [default = %d]\n", nMaxIters ); - fprintf( pErr, "\t-D num : the maximum delay [default = none]\n" ); - fprintf( pErr, "\t-i : enables init state computation [default = %s]\n", fComputeInit? "yes": "no" ); - fprintf( pErr, "\t-f : enables forward-only retiming [default = %s]\n", fForward? "yes": "no" ); - fprintf( pErr, "\t-b : enables backward-only retiming [default = %s]\n", fBackward? "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; -} - -/**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 nMaxLevs; - 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 nMaxLevs, 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; - nMaxLevs = 0; - fUseImps = 0; - fRewrite = 0; - fLatchCorr = 0; - fWriteImps = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PFILirlevh" ) ) != 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 'L': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - nMaxLevs = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nMaxLevs <= 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 0; - } - - 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, nMaxLevs, 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-L num : max number of levels to consider (0=all) [default = %d]\n", nMaxLevs ); - 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-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_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nFrames; - int nWords; - int fVerbose; - extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFrames = 32; - nWords = 8; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FWvh" ) ) != 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 'W': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); - goto usage; - } - nWords = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nWords < 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, "Only works for strashed networks.\n" ); - return 1; - } - if ( !Abc_NtkLatchNum(pNtk) ) - { - fprintf( pErr, "Only works for sequential networks.\n" ); - return 1; - } - - FREE( pNtk->pSeqModel ); - Abc_NtkDarSeqSim( pNtk, nFrames, nWords, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: sim [-F num] [-W num] [-vh]\n" ); - fprintf( pErr, "\t performs random simulation of the sequentail miter\n" ); - fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); - fprintf( pErr, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); - 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_CommandDCec( 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 fSat; - int fVerbose; - int nSeconds; - int nConfLimit; - int nInsLimit; - int fPartition; - int fMiter; - - extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ); - extern int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fPartition, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fSat = 0; - fVerbose = 0; - nSeconds = 20; - nConfLimit = 10000; - nInsLimit = 0; - fPartition = 0; - fMiter = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "TCIpmsvh" ) ) != 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': - fPartition ^= 1; - break; - case 'm': - fMiter ^= 1; - break; - case 's': - fSat ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( fMiter ) - { - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkIsStrash(pNtk) ) - { - pNtk1 = pNtk; - fDelete1 = 0; - } - else - { - pNtk1 = Abc_NtkStrash( pNtk, 0, 1, 0 ); - fDelete1 = 1; - } - pNtk2 = NULL; - fDelete2 = 0; - } - else - { - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) - return 1; - } - - // perform equivalence checking - if ( fSat && fMiter ) - Abc_NtkDSat( pNtk1, nConfLimit, nInsLimit, fVerbose ); - else - Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose ); - - if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); - if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); - return 0; - -usage: - fprintf( pErr, "usage: dcec [-T num] [-C num] [-I num] [-mpsvh] \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-m : toggle working on two networks or a miter [default = %s]\n", fMiter? "miter": "two networks" ); - fprintf( pErr, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" ); - fprintf( pErr, "\t-s : toggle \"SAT only\" (miter) or \"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 (there is also an unbounded SEC commands, \"dsec\" and \"dprove\")\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" ); +usage: + if ( DelayTarget == -1 ) + sprintf( Buffer, "not used" ); + else + sprintf( Buffer, "%.3f", DelayTarget ); + fprintf( pErr, "usage: map [-D num] [-aspvh]\n" ); + fprintf( pErr, "\t performs standard cell mapping of the current network\n" ); + fprintf( pErr, "\t-D num : 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 activity [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"); - 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 [] @@ -12620,90 +3480,53 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; - int fDelete1, fDelete2; - char ** pArgvNew; - int nArgcNew; + Abc_Ntk_t * pNtk; 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 ); + extern int Abc_NtkUnmap( Abc_Ntk_t * pNtk ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != 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; + case 'h': + goto usage; default: goto usage; } } - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); return 1; - - if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + } + if ( !Abc_NtkHasMapping(pNtk) ) { - printf( "The network has no latches. Used combinational command \"cec\".\n" ); - return 0; + fprintf( pErr, "Cannot unmap the network that is not mapped.\n" ); + return 1; } - // perform verification - Abc_NtkDarSec( pNtk1, pNtk2, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); - - if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); - if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + // get the new network + if ( !Abc_NtkUnmap( pNtk ) ) + { + fprintf( pErr, "Unmapping has failed.\n" ); + return 1; + } 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"); + 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; } @@ -12718,83 +3541,58 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAttach( 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_NtkUnmap( Abc_Ntk_t * pNtk ); - extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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, "Frwvh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { - case 'F': - 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; + case 'h': + goto usage; default: goto usage; } } - if ( Abc_NtkLatchNum(pNtk) == 0 ) + if ( pNtk == NULL ) { - printf( "The network has no latches. Used combinational command \"iprove\".\n" ); - return 0; + fprintf( pErr, "Empty network.\n" ); + return 1; } - if ( !Abc_NtkIsStrash(pNtk) ) + + if ( !Abc_NtkIsSopLogic(pNtk) ) { - printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); - return 0; + fprintf( pErr, "Can only attach gates if the nodes have SOP representations.\n" ); + return 1; } - // perform verification - Abc_NtkDarProve( pNtk, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + // get the new network + if ( !Abc_NtkAttach( pNtk ) ) + { + fprintf( pErr, "Attaching gates has failed.\n" ); + return 1; + } return 0; usage: - fprintf( pErr, "usage: dprove [-F num] [-rwvh]\n" ); - fprintf( pErr, "\t performs SEC on the sequential miter\n" ); - fprintf( pErr, "\t-F 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, "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 [] @@ -12806,55 +3604,23 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkRes; int c; - int RetValue; - int fVerbose; - int nConfLimit; - int nInsLimit; - int clk; + extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != 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: @@ -12867,64 +3633,30 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 + if ( !Abc_NtkIsStrash(pNtk) ) { - assert( Abc_NtkIsLogic(pNtk) ); - Abc_NtkToBdd( pNtk ); - RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL ); + fprintf( pErr, "Works only for the AIG representation (run \"strash\").\n" ); + return 1; } - // verify that the pattern is correct - if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) + // get the new network + pNtkRes = Abc_NtkSuperChoice( pNtk ); + if ( pNtkRes == NULL ) { - //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" ); - */ + fprintf( pErr, "Superchoicing has failed.\n" ); + return 1; } - - 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, pNtkRes ); 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 (there is also a newer SAT solving command \"dsat\")\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"); + 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; } @@ -12939,54 +3671,34 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkRes; int c; - int RetValue; + int fRecovery; + int fSwitching; int fVerbose; - int nConfLimit; - int nInsLimit; - int clk; - - extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults + fRecovery = 1; + fSwitching = 0; fVerbose = 0; - nConfLimit = 100000; - nInsLimit = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "apvh" ) ) != 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; + case 'a': + fRecovery ^= 1; 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; + case 'p': + fSwitching ^= 1; break; case 'v': fVerbose ^= 1; @@ -13003,67 +3715,60 @@ int Abc_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 ) + // strash and balance the network + pNtk = Abc_NtkStrash( pNtk, 0, 0 ); + if ( pNtk == NULL ) { - printf( "%d", (int)(pNtk->pModel[i] > 0) ); - if ( i == 70 ) - break; + fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0 ); + 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, fRecovery, fSwitching, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; } - printf( "\n" ); - */ + Abc_NtkDelete( pNtk ); } - - if ( RetValue == -1 ) - printf( "UNDECIDED " ); - else if ( RetValue == 0 ) - printf( "SATISFIABLE " ); else - printf( "UNSATISFIABLE " ); - //printf( "\n" ); - PRT( "Time", clock() - clk ); + { + // get the new network + pNtkRes = Abc_NtkFpga( pNtk, fRecovery, fSwitching, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); 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"); + fprintf( pErr, "usage: fpga [-apvh]\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-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : prints the command usage\n"); return 1; } + + /**Function************************************************************* Synopsis [] @@ -13075,91 +3780,23 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandSeq( 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; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Prove_ParamsSetDefault( pParams ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NCFLIrfbvh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != 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: @@ -13172,62 +3809,31 @@ int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 ); + printf( "This command is not yet implemented.\n" ); + return 0; - // verify that the pattern is correct - if ( RetValue == 0 ) + if ( !Abc_NtkIsStrash(pNtk) ) { - int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); - if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); - free( pSimInfo ); + fprintf( pErr, "Works only for AIG (run \"strash\").\n" ); + return 1; } - - if ( RetValue == -1 ) - printf( "UNDECIDED " ); - else if ( RetValue == 0 ) - printf( "SATISFIABLE " ); - else - printf( "UNSATISFIABLE " ); - //printf( "\n" ); - PRT( "Time", clock() - clk ); + // get the new network + pNtkRes = Abc_NtkAigToSeq( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to sequential AIG has failed.\n" ); + return 1; + } // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); 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 (there are also newer CEC commands, \"iprove\" and \"dprove\")\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"); + fprintf( pErr, "usage: seq [-h]\n" ); + fprintf( pErr, "\t converts AIG into sequential AIG (while sweeping latches)\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -13242,24 +3848,34 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRetime( 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 ); + int fForward; + int fBackward; - pNtk = Abc_FrameReadNtk(pAbc); + extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + fForward = 0; + fBackward = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "fbh" ) ) != EOF ) { switch ( c ) { + case 'f': + fForward ^= 1; + break; + case 'b': + fBackward ^= 1; + break; case 'h': goto usage; default: @@ -13272,22 +3888,36 @@ int Abc_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsLogic(pNtk) ) + + printf( "This command is not yet implemented.\n" ); + return 0; + + + if ( !Abc_NtkIsSeq(pNtk) ) { - fprintf( pErr, "This command is applicable to logic networks.\n" ); + fprintf( pErr, "Works only for sequential AIG.\n" ); return 1; } - Abc_NtkAutoDebug( pNtk, Abc_NtkRetimeDebug ); + // get the new network + if ( fForward ) + Abc_NtkSeqRetimeForward( pNtk ); + else if ( fBackward ) + Abc_NtkSeqRetimeBackward( pNtk ); + else + Abc_NtkSeqRetimeDelay( pNtk ); return 0; usage: - fprintf( pErr, "usage: debug [-h]\n" ); - fprintf( pErr, "\t performs automated debugging of the given procedure\n" ); + fprintf( pErr, "usage: retime [-fbh]\n" ); + fprintf( pErr, "\t retimes sequential AIG (default is Pan's algorithm)\n" ); + fprintf( pErr, "\t-f : toggle forward retiming [default = %s]\n", fForward? "yes": "no" ); + fprintf( pErr, "\t-b : toggle backward retiming [default = %s]\n", fBackward? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } - + + /**Function************************************************************* Synopsis [] @@ -13299,91 +3929,72 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; int c; - int nFrames; - int nBTLimit; - int fRewrite; + int fSat; int fVerbose; -// extern void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose ); - extern int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nFrames, int nBTLimit, int fRewrite, int fVerbose ); + extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); + extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fVerbose ); + - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - nFrames = 5; - nBTLimit = 1000000; - fRewrite = 0; + fSat = 0; fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FCrvh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "svh" ) ) != 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 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nBTLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nBTLimit < 0 ) - goto usage; - break; - case 'r': - fRewrite ^= 1; + case 's': + fSat ^= 1; break; case 'v': fVerbose ^= 1; break; - case 'h': - goto usage; default: goto usage; } } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); + + pArgvNew = argv + util_optind; + nArgcNew = argc - util_optind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); - return 0; - } - Abc_NtkDarBmc( pNtk, nFrames, nBTLimit, fRewrite, fVerbose ); + + // perform equivalence checking + if ( fSat ) + Abc_NtkCecSat( pNtk1, pNtk2 ); + else + Abc_NtkCecFraig( pNtk1, pNtk2, fVerbose ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 0; usage: - fprintf( pErr, "usage: bmc [-F num] [-C num] [-rvh]\n" ); - fprintf( pErr, "\t perform bounded model checking\n" ); - fprintf( pErr, "\t-F num : number of time frames [default = %d]\n", nFrames ); - fprintf( pErr, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit ); - fprintf( pErr, "\t-r : toggle initialization of the first frame [default = %s]\n", fRewrite? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "usage: cec [-svh] \n" ); + fprintf( pErr, "\t performs combinational equivalence checking\n" ); + 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 [] @@ -13395,139 +4006,129 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandIndcut( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int nFrames; - int nPref; - int nClauses; - int nLutSize; - int nLevels; - int nCutsMax; - int nBatches; - int fStepUp; - int fBmc; - int fRegs; - int fVerbose; - int fVeryVerbose; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; int c; - extern int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRegs, int fVerbose, int fVeryVerbose ); + int fSat; + int nFrames; + + extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames ); + extern void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames ); - pNtk = Abc_FrameReadNtk(pAbc); + + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - nFrames = 1; - nPref = 0; - nClauses = 5000; - nLutSize = 4; - nLevels = 8; - nCutsMax = 16; - nBatches = 1; - fStepUp = 0; - fBmc = 1; - fRegs = 1; - fVerbose = 0; - fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FPCMLNBsbrvwh" ) ) != EOF ) + nFrames = 3; + fSat = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "Fsh" ) ) != EOF ) { switch ( c ) { case 'F': - if ( globalUtilOptind >= argc ) + if ( util_optind >= argc ) { fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; + nFrames = atoi(argv[util_optind]); + util_optind++; if ( nFrames < 0 ) goto usage; break; - case 'P': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - nPref = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nPref < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nClauses = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nClauses < 0 ) - goto usage; - break; - case 'M': - 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 'L': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - nLevels = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevels < 0 ) - goto usage; - break; - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCutsMax < 0 ) - goto usage; - break; - case 'B': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); - goto usage; - } - nBatches = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nBatches < 0 ) - goto usage; - break; case 's': - fStepUp ^= 1; + fSat ^= 1; break; - case 'b': - fBmc ^= 1; + default: + goto usage; + } + } + + pArgvNew = argv + util_optind; + nArgcNew = argc - util_optind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + // perform equivalence checking + if ( fSat ) + Abc_NtkSecSat( pNtk1, pNtk2, nFrames ); + else + Abc_NtkSecFraig( pNtk1, pNtk2, nFrames ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + fprintf( pErr, "usage: sec [-sh] [-F num] \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-h : print the command usage\n"); + fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames ); + 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_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 ); + extern Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNet(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fLatchSweep = 0; + fAutoSweep = 0; + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "lavh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fLatchSweep ^= 1; break; - case 'r': - fRegs ^= 1; + case 'a': + fAutoSweep ^= 1; break; case 'v': fVerbose ^= 1; break; - case 'w': - fVeryVerbose ^= 1; - break; case 'h': goto usage; default: @@ -13539,42 +4140,41 @@ int Abc_CommandIndcut( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( Abc_NtkIsComb(pNtk) ) + if ( !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "Only works for sequential networks.\n" ); + fprintf( pErr, "Only works for structrally hashed networks.\n" ); return 1; } - if ( !Abc_NtkIsStrash(pNtk) ) + if ( !Abc_NtkLatchNum(pNtk) ) { - fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); - return 0; + fprintf( pErr, "Only works for sequential networks.\n" ); + return 1; } - if ( nLutSize > 12 ) + // modify the current network + pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchSweep, fVerbose ); +// pNtkRes = Abc_NtkDar( pNtk ); + if ( pNtkRes == NULL ) { - fprintf( stdout, "The cut size should be not exceed 12.\n" ); - return 0; + fprintf( pErr, "Sequential cleanup has failed.\n" ); + return 1; } - Abc_NtkDarClau( pNtk, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRegs, fVerbose, fVeryVerbose ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; + usage: - fprintf( pErr, "usage: indcut [-FPCMLNB num] [-bvh]\n" ); - fprintf( pErr, "\t K-step induction strengthened with cut properties\n" ); - fprintf( pErr, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFrames ); - fprintf( pErr, "\t-P num : number of time frames in the prefix (0=no prefix) [default = %d]\n", nPref ); - fprintf( pErr, "\t-C num : the max number of clauses to use for strengthening [default = %d]\n", nClauses ); - fprintf( pErr, "\t-M num : the cut size (2 <= M <= 12) [default = %d]\n", nLutSize ); - fprintf( pErr, "\t-L num : the max number of levels for cut computation [default = %d]\n", nLevels ); - fprintf( pErr, "\t-N num : the max number of cuts to compute at a node [default = %d]\n", nCutsMax ); - fprintf( pErr, "\t-B num : the max number of invariant batches to try [default = %d]\n", nBatches ); - fprintf( pErr, "\t-s : toggle increment cut size in each batch [default = %s]\n", fStepUp? "yes": "no" ); - fprintf( pErr, "\t-b : toggle enabling BMC check [default = %s]\n", fBmc? "yes": "no" ); - fprintf( pErr, "\t-r : toggle enabling register clauses [default = %s]\n", fRegs? "yes": "no" ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); -// fprintf( pErr, "\t-w : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); + 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-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 [] @@ -13586,36 +4186,49 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandEnlarge( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkRes; - int nFrames; - int fVerbose; int c; - extern Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); + 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); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - nFrames = 5; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF ) + nFramesP = 0; + nConfMax = 10000; + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "PCvh" ) ) != EOF ) { switch ( c ) { - case 'F': - if ( globalUtilOptind >= argc ) + case 'P': + if ( util_optind >= argc ) { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames < 0 ) + nFramesP = atoi(argv[util_optind]); + util_optind++; + if ( nFramesP < 0 ) + goto usage; + break; + case 'C': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfMax = atoi(argv[util_optind]); + util_optind++; + if ( nConfMax < 0 ) goto usage; break; case 'v': @@ -13627,42 +4240,46 @@ int Abc_CommandEnlarge( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } + if ( Abc_NtkIsComb(pNtk) ) { - fprintf( pErr, "Only works for sequential networks.\n" ); + fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); return 1; } + if ( !Abc_NtkIsStrash(pNtk) ) { - fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } - // modify the current network - pNtkRes = Abc_NtkDarEnlarge( pNtk, nFrames, fVerbose ); + // get the new network + pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose ); if ( pNtkRes == NULL ) { - fprintf( pErr, "Target enlargement has failed.\n" ); + fprintf( pErr, "Sequential sweeping has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; + usage: - fprintf( pErr, "usage: enlarge [-F num] [-vh]\n" ); - fprintf( pErr, "\t performs structural K-step target enlargement\n" ); - fprintf( pErr, "\t-F num : the number of timeframes for enlargement [default = %d]\n", nFrames ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + 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 [] @@ -13674,22 +4291,100 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkRes; int c; + int nFramesP; + int nFramesK; + int nMaxImps; + int nMaxLevs; + 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 nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose ); - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + nFramesP = 0; + nFramesK = 1; + nMaxImps = 5000; + nMaxLevs = 0; + fUseImps = 0; + fRewrite = 0; + fLatchCorr = 0; + fWriteImps = 0; + fVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "PFILirlevh" ) ) != EOF ) { switch ( c ) { + case 'P': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nFramesP = atoi(argv[util_optind]); + util_optind++; + if ( nFramesP < 0 ) + goto usage; + break; + case 'F': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFramesK = atoi(argv[util_optind]); + util_optind++; + if ( nFramesK <= 0 ) + goto usage; + break; + case 'I': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nMaxImps = atoi(argv[util_optind]); + util_optind++; + if ( nMaxImps <= 0 ) + goto usage; + break; + case 'L': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nMaxLevs = atoi(argv[util_optind]); + util_optind++; + if ( nMaxLevs <= 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: @@ -13702,25 +4397,43 @@ int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); + return 0; + } + if ( !Abc_NtkIsStrash(pNtk) ) { - fprintf( pErr, "This command is applicable to AIGs.\n" ); - return 1; + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; } -/* - Abc_HManStart(); - if ( !Abc_HManPopulate( pNtk ) ) + + // get the new network + pNtkRes = Abc_NtkDarSeqSweep( pNtk, nFramesP, nFramesK, nMaxImps, nMaxLevs, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose ); + if ( pNtkRes == NULL ) { - fprintf( pErr, "Failed to start the tracing database.\n" ); + fprintf( pErr, "Sequential sweeping has failed.\n" ); return 1; } -*/ + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); 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"); + fprintf( pErr, "usage: ssweep [-P num] [-F num] [-lrevh]\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-L num : max number of levels to consider (0=all) [default = %d]\n", nMaxLevs ); +// 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; } @@ -13735,59 +4448,94 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + 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); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + nFrames =16; + fRetimeFirst = 1; + fVerbose = 0; + fVeryVerbose = 0; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "Krwvh" ) ) != EOF ) { switch ( c ) { - case 'h': - goto usage; + case 'K': + if ( util_optind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[util_optind]); + util_optind++; + 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 ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command is applicable to AIGs.\n" ); + pArgvNew = argv + util_optind; + nArgcNew = argc - util_optind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; - } -/* - if ( !Abc_HManIsRunning(pNtk) ) + + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) { - fprintf( pErr, "The tracing database is not available.\n" ); - return 1; + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; } - if ( !Abc_HManVerify( 1, pNtk->Id ) ) - fprintf( pErr, "Verification failed.\n" ); - Abc_HManStop(); -*/ + // 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: trace_check [-h]\n" ); - fprintf( pErr, "\t checks the current network using verification trace\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); + 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; } + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcAttach.c b/src/base/abci/abcAttach.c index d5d2aa16..6ee1fb90 100644 --- a/src/base/abci/abcAttach.c +++ b/src/base/abci/abcAttach.c @@ -40,7 +40,7 @@ static char ** s_pPerms = NULL; static int s_nPerms; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -66,7 +66,7 @@ int Abc_NtkAttach( Abc_Ntk_t * pNtk ) assert( Abc_NtkIsSopLogic(pNtk) ); // check that the library is available - pGenlib = Abc_FrameReadLibGen(); + pGenlib = Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()); if ( pGenlib == NULL ) { printf( "The current library is not available.\n" ); @@ -142,7 +142,7 @@ int Abc_NtkAttach( Abc_Ntk_t * pNtk ) Abc_NtkForEachNode( pNtk, pNode, i ) pNode->pData = pNode->pCopy, pNode->pCopy = NULL; pNtk->ntkFunc = ABC_FUNC_MAP; - Extra_MmFlexStop( pNtk->pManFunc ); + Extra_MmFlexStop( pNtk->pManFunc, 0 ); pNtk->pManFunc = pGenlib; printf( "Library gates are successfully attached to the nodes.\n" ); @@ -187,7 +187,7 @@ int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTrut Abc_ObjForEachFanin( pNode, pFanin, i ) pTempInts[i] = pFanin->Id; for ( i = 0; i < nFanins; i++ ) - pNode->vFanins.pArray[Perm[i]] = pTempInts[i]; + pNode->vFanins.pArray[Perm[i]].iFan = pTempInts[i]; // set the gate pNode->pCopy = (Abc_Obj_t *)pGate; return 1; @@ -387,13 +387,13 @@ void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned nMints = (1 << nVars); for ( iMint = 0; iMint < nMints; iMint++ ) { - if ( (uTruthNode[iMint>>5] & (1 << (iMint&31))) == 0 ) + if ( (uTruthNode[iMint/32] & (1 << (iMint%32))) == 0 ) continue; iMintPerm = 0; for ( v = 0; v < nVars; v++ ) if ( iMint & (1 << v) ) iMintPerm |= (1 << pPerm[v]); - uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31)); + uTruthPerm[iMintPerm/32] |= (1 << (iMintPerm%32)); } } 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 index f9b3384e..40701e41 100644 --- a/src/base/abci/abcBalance.c +++ b/src/base/abci/abcBalance.c @@ -24,16 +24,13 @@ /// 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 ); - +static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate ); +static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, bool fDuplicate ); +static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int fDuplicate ); +static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -47,32 +44,14 @@ static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ); SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ) +Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate ) { - 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 ); + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG ); + Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate ); 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 ) ) { @@ -94,7 +73,7 @@ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, SeeAlso [] ***********************************************************************/ -void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ) +void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate ) { int fCheck = 1; ProgressBar * pProgress; @@ -102,10 +81,12 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica Abc_Obj_t * pNode, * pDriver; int i; + // copy the constant node + Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkAig->pManFunc); // 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 ); + vStorage = Vec_VecStart( Abc_AigGetLevelNum(pNtk) + 1 ); // perform balancing of POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) @@ -113,103 +94,12 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica Extra_ProgressBarUpdate( pProgress, i, NULL ); // strash the driver node pDriver = Abc_ObjFanin0(pNode); - Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel ); + Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, fDuplicate ); } 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.] @@ -221,44 +111,36 @@ void Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBo 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_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, bool fDuplicate ) { Abc_Aig_t * pMan = pNtkNew->pManFunc; Abc_Obj_t * pNodeNew, * pNode1, * pNode2; Vec_Ptr_t * vSuper; - int i, LeftBound; + int i; 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 ); + vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, fDuplicate ); if ( vSuper->nSize == 0 ) { // it means that the supergate contains two nodes in the opposite polarity - pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pNtkNew)); + pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pMan)); 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 ); + pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, fDuplicate ); 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) ); @@ -267,13 +149,6 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_ 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; } @@ -290,25 +165,17 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_ SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, bool fSelective ) +Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int fDuplicate ) { 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 ); + vNodes = Vec_VecEntry( vStorage, pNode->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 + RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate ); + assert( vNodes->nSize > 0 ); 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; @@ -328,7 +195,7 @@ Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Le SeeAlso [] ***********************************************************************/ -int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ) +int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate ) { int RetValue1, RetValue2, i; // check if the node is visited @@ -346,7 +213,7 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, 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)) ) + if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && (Abc_ObjFanoutNum(pNode) > 1)) ) { Vec_PtrPush( vSuper, pNode ); Abc_ObjRegular(pNode)->fMarkB = 1; @@ -355,8 +222,8 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, 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 ); + RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate ); + RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; // return 1 if at least one branch has a duplicate @@ -364,248 +231,6 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, } -/**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 a6b3a770..00000000 --- a/src/base/abci/abcClpBdd.c +++ /dev/null @@ -1,181 +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" -//#include "reo.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; -} - - -//int runtime1, runtime2; - -/**Function************************************************************* - - Synopsis [Derives the network with the given global BDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) -{ -// extern void Extra_ShuffleTest( reo_man * p, DdManager * dd, DdNode * Func ); -// reo_man * pReo; - - ProgressBar * pProgress; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode, * pDriver, * pNodeNew; -// DdManager * dd = pNtk->pManGlob; - DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); - int i; - -// pReo = Extra_ReorderInit( Abc_NtkCiNum(pNtk), 1000 ); -// runtime1 = runtime2 = 0; - - // 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_ShuffleTest( pReo, dd, Abc_ObjGlobalBdd(pNode) ); - - } - Extra_ProgressBarStop( pProgress ); - -// Extra_ReorderQuit( pReo ); -//PRT( "Reo ", runtime1 ); -//PRT( "Cudd", runtime2 ); - - 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/abcCollapse.c b/src/base/abci/abcCollapse.c new file mode 100644 index 00000000..40370eff --- /dev/null +++ b/src/base/abci/abcCollapse.c @@ -0,0 +1,146 @@ +/**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 DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collapses the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + + assert( Abc_NtkIsStrash(pNtk) ); + + // compute the global BDDs + if ( Abc_NtkGlobalBdds(pNtk, 0) == NULL ) + return NULL; + if ( fVerbose ) + printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) ); + + // create the new network + pNtkNew = Abc_NtkFromGlobalBdds( pNtk ); + Abc_NtkFreeGlobalBdds( pNtk ); + 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 ); + + // 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, * pNodeNew; + DdManager * dd = pNtk->pManGlob; + int i; + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_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 ); + pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) ); + 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/abcCut.c b/src/base/abci/abcCut.c index d399ce5f..f487bd1b 100644 --- a/src/base/abci/abcCut.c +++ b/src/base/abci/abcCut.c @@ -25,16 +25,8 @@ /// 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -50,30 +42,18 @@ static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ); ***********************************************************************/ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) { - ProgressBar * pProgress; Cut_Man_t * p; - Abc_Obj_t * pObj, * pNode; + Abc_Obj_t * pObj, * pDriver, * 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 @@ -81,9 +61,8 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( p, pObj->Id ); // compute cuts for internal nodes - vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs + vNodes = Abc_AigDfs( pNtk, 0, 1 ); 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 @@ -94,19 +73,12 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) continue; } // skip constant node, it has no cuts -// if ( Abc_NodeIsConst(pObj) ) -// continue; - Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( Abc_NodeIsConst(pObj) ) + continue; // 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) ); - } + Abc_NodeGetCuts( p, pObj ); // add cuts due to choices - if ( Abc_AigNodeIsChoice(pObj) ) + if ( Abc_NodeIsAigChoice(pObj) ) { Vec_IntClear( vChoices ); for ( pNode = pObj; pNode; pNode = pNode->pData ) @@ -114,203 +86,31 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) 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 ) + if ( !pParams->fSeq ) { - // 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 ); + Vec_IntFree( vChoices ); +PRT( "Total", clock() - clk ); + return p; } - Vec_PtrFree( vNodes ); -//PRT( "Total", clock() - clk ); -//Abc_NtkPrintCuts_( p, pNtk, 0 ); -} - + assert( 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++ ) + // compute sequential cuts + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachLatch( pNtk, pObj, i ) { -//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; + pDriver = Abc_ObjFanin0(pObj); + if ( !Abc_ObjIsNode(pDriver) ) + continue; + if ( Abc_NodeIsTravIdCurrent(pDriver) ) + continue; + Abc_NodeSetTravIdCurrent(pDriver); + Cut_NodeSetComputedAsNew( p, pDriver->Id ); } - Vec_IntFree( vChoices ); + // compute as long as new cuts appear - // 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************************************************************* @@ -324,14 +124,14 @@ int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ) SeeAlso [] ***********************************************************************/ -void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) +void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj ) { 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 ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj) ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj) ); + return Abc_NodeGetCuts( p, pObj ); } /**Function************************************************************* @@ -345,73 +145,10 @@ void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree SeeAlso [] ***********************************************************************/ -void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) +void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj ) { - 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 ); -*/ + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); } /**Function************************************************************* @@ -427,7 +164,7 @@ void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) ***********************************************************************/ void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) { - return Cut_NodeReadCutsNew( p, pObj->Id ); + return Cut_NodeReadCuts( p, pObj->Id ); } /**Function************************************************************* @@ -446,173 +183,6 @@ 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 index 42ac528b..39f58a4e 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -22,13 +22,16 @@ #include "aig.h" #include "dar.h" #include "cnf.h" -#include "fra.h" -#include "fraig.h" +//#include "fra.h" +//#include "fraig.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \ + for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -53,25 +56,6 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ) // 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) ); - if ( !Abc_ObjIsPi(pObj) ) - printf( "Abc_NtkToDar(): Temporary bug: The PI ordering is wrong!\n" ); - } - else - assert( Abc_ObjIsBo(pObj) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - if ( i < Abc_NtkPoNum(pNtk) ) - { - assert( Abc_ObjIsPo(pObj) ); - if ( !Abc_ObjIsPo(pObj) ) - printf( "Abc_NtkToDar(): Temporary bug: The PO ordering is wrong!\n" ); - } - else - assert( Abc_ObjIsBi(pObj) ); // print warning about initial values nDontCares = 0; Abc_NtkForEachLatch( pNtk, pObj, i ) @@ -90,7 +74,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ) } // create the manager pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 ); - pMan->pName = Extra_UtilStrsav( pNtk->pName ); + pMan->pName = util_strsav( pNtk->pName ); // save the number of registers if ( fRegisters ) { @@ -99,7 +83,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ) pMan->vFlopNums = NULL; } // transfer the pointers to the basic nodes - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); + Abc_AigConst1(pNtk->pManFunc)->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 @@ -111,6 +95,8 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ) // pMan->fAddStrash = 1; Abc_NtkForEachNode( pNtk, pObj, i ) { + if ( Abc_ObjFaninNum(pObj) == 0 ) + continue; 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 ); } @@ -121,7 +107,8 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ) // complement the 1-valued registers if ( fRegisters ) Aig_ManForEachLiSeq( pMan, pObjNew, i ) - if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) ) +// if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) ) + if ( Abc_LatchIsInit1(Abc_NtkCo(pNtk,i)) ) pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0); // remove dangling nodes if ( nNodes = Aig_ManCleanup( pMan ) ) @@ -151,14 +138,14 @@ 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; +// 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 ); + pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_TYPE_STRASH, ABC_FUNC_AIG ); // transfer the pointers to the basic nodes - Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc); Aig_ManForEachPi( pMan, pObj, i ) pObj->pData = Abc_NtkCi(pNtkNew, i); // rebuild the AIG @@ -176,6 +163,7 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) 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 ) @@ -184,11 +172,36 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) 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 [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyLatchNames( Abc_Ntk_t * pNtk ) +{ + char Buffer[100]; + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + sprintf( Buffer, "L%0*d", nDigits, i ); + Abc_NtkLogicStoreName( pObj, Buffer ); + } +} + /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] @@ -204,52 +217,38 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) 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; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjOld, * pObjNew; Aig_Obj_t * pObj, * pObjLo, * pObjLi; - int i, iNodeId; -// assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) ); - // perform strashing - pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // consider the case of target enlargement - if ( Abc_NtkCiNum(pNtkNew) < Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) ) + int i; + // start the network + pNtkNew = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG ); + // duplicate the name and the spec + pNtkNew->pName = util_strsav(pNtkOld->pName); + pNtkNew->pSpec = util_strsav(pNtkOld->pSpec); + // create PIs/POs/latches + Abc_NtkForEachPi( pNtkOld, pObjOld, i ) { - for ( i = Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) - Abc_NtkCiNum(pNtkNew); i > 0; i-- ) - { - pObjNew = Abc_NtkCreatePi( pNtkNew ); - Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL ); - } - Abc_NtkOrderCisCos( pNtkNew ); + pObjNew = Abc_NtkDupObj( pNtkNew, pObjOld ); + Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObjOld) ); + } + Abc_NtkForEachPo( pNtkOld, pObjOld, i ) + { + pObjNew = Abc_NtkDupObj( pNtkNew, pObjOld ); + Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObjOld) ); } - assert( Abc_NtkCiNum(pNtkNew) == Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) ); - assert( Abc_NtkCoNum(pNtkNew) == Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) ); - // 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 ); + Vec_PtrPush( pNtkNew->vCis, pObjNew ); + Vec_PtrPush( pNtkNew->vCos, 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 ); - } - } + Abc_NtkAddDummyLatchNames( pNtkNew ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc); + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); // rebuild the AIG vNodes = Aig_ManDfs( pMan ); Vec_PtrForEachEntry( vNodes, pObj, i ) @@ -261,23 +260,9 @@ Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) // connect the PO nodes Aig_ManForEachPo( pMan, pObj, i ) { - if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts ) - break; - iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(Abc_NtkCo(pNtkNew, i)), ABC_OBJ_PI, ABC_OBJ_BO ); - if ( iNodeId >= 0 ) - pObjNew = Abc_NtkObj( pNtkNew, iNodeId ); - else - pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); + pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew ); } - // 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; @@ -303,9 +288,9 @@ Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) assert( pMan->pEquivs != NULL ); assert( Aig_ManBufNum(pMan) == 0 ); // perform strashing - pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_TYPE_STRASH, ABC_FUNC_AIG ); // transfer the pointers to the basic nodes - Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc); Aig_ManForEachPi( pMan, pObj, i ) pObj->pData = Abc_NtkCi(pNtkNew, i); @@ -334,154 +319,6 @@ Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) 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.] @@ -520,43 +357,6 @@ Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ) 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.] @@ -568,61 +368,57 @@ Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, in SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ) +Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, 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 ); + Aig_Man_t * pMan; + pMan = Abc_NtkToDar( pNtk, 1 ); if ( pMan == NULL ) return NULL; - pMan = Csw_Sweep( pTemp = pMan, nCutsMax, nLeafMax, fVerbose ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pTemp ); + 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.] + Synopsis [Computes latch correspondence.] Description [] SideEffects [] SeeAlso [] - + ***********************************************************************/ -Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ) +Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ) { + extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter ); Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig; - int clk; - assert( Abc_NtkIsStrash(pNtk) ); - pMan = Abc_NtkToDar( pNtk, 0 ); + pMan = Abc_NtkToDar( pNtk, 1 ); if ( pMan == NULL ) return NULL; -// Aig_ManPrintStats( pMan ); -/* -// Aig_ManSupports( pMan ); + 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 { - Vec_Vec_t * vParts; - vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL ); - Vec_VecFree( vParts ); + Abc_Obj_t * pObj; + int i; + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Abc_NtkForEachLatch( pNtkAig, pObj, i ) + Abc_LatchSetInit0( pObj ); } -*/ - 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; } @@ -638,61 +434,44 @@ clk = clock(); SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ) +Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, int nMaxImps, int nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose ) { + extern Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, int nFramesP, int nFramesK, int nMaxImps, int nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose, int * pnIter ); +// Fraig_Params_t Params; + Abc_Ntk_t * pNtkAig, * pNtkFraig; 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 ); + int clk = clock(); -// Aig_ManPrintStats( pMan ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; + // 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 ); } -/**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 ); + pMan = Abc_NtkToDar( pNtkFraig, 1 ); + Abc_NtkDelete( pNtkFraig ); if ( pMan == NULL ) return NULL; -// Aig_ManPrintStats( pMan ); -clk = clock(); - pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fVerbose ); + pMan = Fra_FraigInduction( pTemp = pMan, nFramesP, nFramesK, nMaxImps, nMaxLevs, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose, NULL ); Aig_ManStop( pTemp ); -//PRT( "time", clock() - clk ); -// Aig_ManPrintStats( pMan ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + else + { + Abc_Obj_t * pObj; + int i; + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Abc_NtkForEachLatch( pNtkAig, pObj, i ) + Abc_LatchSetInit0( pObj ); + } Aig_ManStop( pMan ); return pNtkAig; } @@ -708,488 +487,16 @@ clk = clock(); 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 ) -{ - Aig_Man_t * pMan; - int RetValue;//, clk = clock(); - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkLatchNum(pNtk) == 0 ); - assert( Abc_NtkPoNum(pNtk) == 1 ); - pMan = Abc_NtkToDar( pNtk, 0 ); - RetValue = Fra_FraigSat( pMan, nConfLimit, nInsLimit, fVerbose ); - pNtk->pModel = pMan->pData, pMan->pData = NULL; - Aig_ManStop( pMan ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fPartition, int fVerbose ) -{ - Aig_Man_t * pMan, * pMan1, * pMan2; - Abc_Ntk_t * pMiter; - int RetValue, clkTotal = clock(); - - // cannot partition if it is already a miter - if ( pNtk2 == NULL && fPartition == 1 ) - { - printf( "Abc_NtkDarCec(): Switching to non-partitioned CEC for the miter.\n" ); - fPartition = 0; - } - - // if partitioning is selected, call partitioned CEC - if ( fPartition ) - { - pMan1 = Abc_NtkToDar( pNtk1, 0 ); - pMan2 = Abc_NtkToDar( pNtk2, 0 ); - RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, fVerbose ); - Aig_ManStop( pMan1 ); - Aig_ManStop( pMan2 ); - goto finish; - } - - if ( pNtk2 != NULL ) - { - // 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; - } - } - else - { - pMiter = Abc_NtkDup( pNtk1 ); - } - 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 - if ( pNtk2 == NULL ) - pNtk1->pModel = Abc_NtkVerifyGetCleanModel( pNtk1, 1 ); -// 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, 0 ); - Abc_NtkDelete( pMiter ); - if ( pMan == NULL ) - { - printf( "Converting miter into AIG has failed.\n" ); - return -1; - } - // perform verification - RetValue = Fra_FraigCec( &pMan, fVerbose ); - // transfer model if given - if ( pNtk2 == NULL ) - pNtk1->pModel = pMan->pData, pMan->pData = NULL; - Aig_ManStop( pMan ); - -finish: - // 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 - { - printf( "Networks are UNDECIDED. " ); -PRT( "Time", clock() - clkTotal ); - } - fflush( stdout ); - 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 nMaxLevs, 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, nMaxLevs, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose, NULL ); - Aig_ManStop( pTemp ); - - if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) - pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); - else - { - Abc_Obj_t * pObj; - int i; - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Abc_NtkForEachLatch( pNtkAig, pObj, i ) - Abc_LatchSetInit0( pObj ); - } - 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 - { - Abc_Obj_t * pObj; - int i; - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Abc_NtkForEachLatch( pNtkAig, pObj, i ) - Abc_LatchSetInit0( pObj ); - } - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nFrames, int nBTLimit, int fRewrite, int fVerbose ) -{ - Aig_Man_t * pMan; - int clk = clock(); - // 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 - Fra_BmcPerformSimple( pMan, nFrames, nBTLimit, fRewrite, fVerbose ); - pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; - if ( pNtk->pSeqModel ) - { - Fra_Cex_t * pCex = pNtk->pSeqModel; - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump the trace). ", pCex->iPo, pCex->iFrame ); - } - else - printf( "No output was asserted after BMC with %d frames. ", nFrames ); -PRT( "Time", clock() - clk ); - Aig_ManStop( pMan ); - return 1; -} - -/**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 ); - pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; - if ( pNtk->pSeqModel ) - { - Fra_Cex_t * pCex = pNtk->pSeqModel; - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump the trace).\n", pCex->iPo, pCex->iFrame ); - } - 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 ) +int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ) { + extern int Fra_FraigSec( Aig_Man_t * p, int nFramesMax, 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 ); + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); @@ -1200,10 +507,12 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetim { 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; } @@ -1258,314 +567,7 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetim 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 ); - if ( pMan->vFlopNums ) - Vec_IntFree( pMan->vFlopNums ); - pMan->vFlopNums = NULL; - - 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; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarRetimeF( 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 ); - if ( pMan->vFlopNums ) - Vec_IntFree( pMan->vFlopNums ); - pMan->vFlopNums = NULL; - - pMan = Aig_ManRetimeFrontier( pTemp = pMan, nStepsMax ); - Aig_ManStop( pTemp ); - -// pMan = Aig_ManReduceLaches( pMan, 1 ); -// pMan = Aig_ManConstReduce( pMan, 1 ); - - 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 [] - -***********************************************************************/ -void Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk ) -{ - Aig_Man_t * pMan; - pMan = Abc_NtkToDar( pNtk, 1 ); - if ( pMan == NULL ) - return; -// Aig_ManReduceLachesCount( pMan ); - if ( pMan->vFlopNums ) - Vec_IntFree( pMan->vFlopNums ); - pMan->vFlopNums = NULL; - Aig_ManHaigRecord( pMan ); - Aig_ManStop( pMan ); -} - -/**Function************************************************************* - - Synopsis [Performs random simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose ) -{ - Aig_Man_t * pMan; - Fra_Sml_t * pSml; - Fra_Cex_t * pCex; - int RetValue, clk = clock(); - pMan = Abc_NtkToDar( pNtk, 1 ); - pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords ); - if ( pSml->fNonConstOut ) - { - pCex = Fra_SmlGetCounterExample( pSml ); - if ( pCex ) - printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ", - nFrames, nWords, pCex->iPo, pCex->iFrame ); - pNtk->pSeqModel = pCex; - RetValue = 1; - } - else - { - RetValue = 0; - printf( "Simulation of %d frames with %d words did not assert the outputs. ", - nFrames, nWords ); - } - PRT( "Time", clock() - clk ); - Fra_SmlStop( pSml ); - Aig_ManStop( pMan ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fVerbose, int fVeryVerbose ) -{ - extern int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose ); - extern int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fVerbose, int fVeryVerbose ); - Aig_Man_t * pMan; - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - printf( "The number of outputs should be 1.\n" ); - return 1; - } - pMan = Abc_NtkToDar( pNtk, 1 ); - if ( pMan == NULL ) - return 1; -// Aig_ManReduceLachesCount( pMan ); - if ( pMan->vFlopNums ) - Vec_IntFree( pMan->vFlopNums ); - pMan->vFlopNums = NULL; - -// Fra_Clau( pMan, nStepsMax, fVerbose, fVeryVerbose ); - Fra_Claus( pMan, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRefs, fVerbose, fVeryVerbose ); - Aig_ManStop( pMan ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs targe enlargement.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) -{ - Abc_Ntk_t * pNtkAig; - Aig_Man_t * pMan, * pTemp; - pMan = Abc_NtkToDar( pNtk, 1 ); - if ( pMan == NULL ) - return NULL; - pMan = Aig_ManFrames( pTemp = pMan, nFrames, 0, 1, 1, 1, NULL ); - Aig_ManStop( pTemp ); - pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Interplates two networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fVerbose ) -{ - extern Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose ); - Abc_Ntk_t * pNtkAig; - Aig_Man_t * pManOn, * pManOff, * pManAig; - if ( Abc_NtkCoNum(pNtkOn) != 1 || Abc_NtkCoNum(pNtkOff) != 1 ) - { - printf( "Currently works only for single output networks.\n" ); - return NULL; - } - if ( Abc_NtkCiNum(pNtkOn) != Abc_NtkCiNum(pNtkOff) ) - { - printf( "The number of PIs should be the same.\n" ); - return NULL; - } - // create internal AIGs - pManOn = Abc_NtkToDar( pNtkOn, 0 ); - if ( pManOn == NULL ) - return NULL; - pManOff = Abc_NtkToDar( pNtkOff, 0 ); - if ( pManOff == NULL ) - return NULL; - // derive the interpolant - pManAig = Aig_ManInter( pManOn, pManOff, fVerbose ); - if ( pManAig == NULL ) - { - printf( "Interpolant computation failed.\n" ); - return NULL; - } - Aig_ManStop( pManOn ); - Aig_ManStop( pManOff ); - // create logic network - pNtkAig = Abc_NtkFromDar( pNtkOn, pManAig ); - Aig_ManStop( pManAig ); - return pNtkAig; -} - - -#include "ntl.h" -/**Function************************************************************* - - Synopsis [Performs targe enlargement.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDarTestBlif( char * pFileName ) -{ - char Buffer[1000]; - Ntl_Man_t * p; - p = Ioa_ReadBlif( pFileName, 1 ); - if ( p == NULL ) - { - printf( "Abc_NtkDarTestBlif(): Reading BLIF has failed.\n" ); - return; - } - Ntl_ManPrintStats( p ); -// if ( !Ntl_ManInsertTest( p ) ) - if ( !Ntl_ManInsertTestIf( p ) ) - { - printf( "Abc_NtkDarTestBlif(): Tranformation of the netlist has failed.\n" ); - return; - } -// sprintf( Buffer, "%s_.blif", p->pName ); - sprintf( Buffer, "test_.blif", p->pName ); - Ioa_WriteBlif( p, Buffer ); - Ntl_ManFree( p ); -} //////////////////////////////////////////////////////////////////////// /// 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 index c00a7d7c..67665ad6 100644 --- a/src/base/abci/abcDsd.c +++ b/src/base/abci/abcDsd.c @@ -27,15 +27,15 @@ 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 Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew ); 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 void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive ); static bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ); static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -55,22 +55,28 @@ static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int n ***********************************************************************/ 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 ) + + // perform FPGA mapping + if ( Abc_NtkGlobalBdds(pNtk, 0) == NULL ) return NULL; if ( fVerbose ) - printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) ); + // transform the result of mapping into a BDD network pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort ); - Extra_StopManager( dd ); if ( pNtkNew == NULL ) + { + Cudd_Quit( pNtk->pManGlob ); + pNtk->pManGlob = NULL; return NULL; - // copy EXDC network - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + } + Extra_StopManager( pNtk->pManGlob ); + pNtk->pManGlob = NULL; + + // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkDsdGlobal: The network check has failed.\n" ); @@ -93,25 +99,26 @@ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool ***********************************************************************/ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) { - char ** ppNamesCi, ** ppNamesCo; - Vec_Ptr_t * vFuncsGlob; + DdManager * dd = pNtk->pManGlob; Dsd_Manager_t * pManDsd; Abc_Ntk_t * pNtkNew; - DdManager * dd; + DdNode * bFunc; + char ** ppNamesCi, ** ppNamesCo; 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)) ); + { + bFunc = Vec_PtrEntry(pNtk->vFuncsGlob, i); + Vec_PtrWriteEntry(pNtk->vFuncsGlob, i, Cudd_NotCond(bFunc, Abc_ObjFaninC0(pObj)) ); + } // perform the decomposition - dd = Abc_NtkGlobalBddMan(pNtk); + assert( Vec_PtrSize(pNtk->vFuncsGlob) == Abc_NtkCoNum(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 ); + Dsd_Decompose( pManDsd, (DdNode **)pNtk->vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) ); + Abc_NtkFreeGlobalBdds( pNtk ); if ( pManDsd == NULL ) { Cudd_Quit( dd ); @@ -119,7 +126,7 @@ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bo } // start the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_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) @@ -128,6 +135,7 @@ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bo Abc_NtkFinalize( pNtk, pNtkNew ); // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + if ( fPrint ) { ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 ); @@ -157,21 +165,24 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * { Dsd_Node_t ** ppNodesDsd; Dsd_Node_t * pNodeDsd; - Abc_Obj_t * pNode, * pNodeNew, * pDriver; + Abc_Obj_t * pNode, * pNodeNew, * pDriver, * pConst1; 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 ); } + // set the constant node + pConst1 = Abc_AigConst1(pNtk->pManFunc); + if ( Abc_ObjFanoutNum(pConst1) > 0 ) + pConst1->pCopy = Abc_NodeCreateConst1(pNtkNew); // 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 ); + Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew ); free( ppNodesDsd ); // set the pointers to the CO drivers @@ -180,7 +191,7 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pDriver = Abc_ObjFanin0( pNode ); if ( !Abc_ObjIsNode(pDriver) ) continue; - if ( !Abc_AigNodeIsAnd(pDriver) ) + if ( !Abc_NodeIsAigAnd(pDriver) ) continue; pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i ); pNodeNew = (Abc_Obj_t *)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) ); @@ -200,7 +211,7 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ) +Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew ) { DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd ); DdManager * ddNew = pNtkNew->pManFunc; @@ -257,22 +268,8 @@ Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNode } 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; @@ -310,7 +307,6 @@ int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive ) DdManager * dd = pNtk->pManFunc; Vec_Ptr_t * vNodes; int i; - int pCounters[11] = {0}; assert( Abc_NtkIsBddLogic(pNtk) ); @@ -323,14 +319,9 @@ int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive ) // collect nodes for decomposition vNodes = Abc_NtkCollectNodesForDsd( pNtk ); for ( i = 0; i < vNodes->nSize; i++ ) - Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive, pCounters ); + Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive ); 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 ); @@ -380,7 +371,7 @@ Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters ) +void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive ) { DdManager * dd = pNode->pNtk->pManFunc; Abc_Obj_t * pRoot, * pFanin, * pNode1, * pNode2, * pNodeC; @@ -407,7 +398,7 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd ); for ( i = 0; i < nNodesDsd; i++ ) { - pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters ); + pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk ); if ( Abc_NodeIsForDsd(pRoot) && fRecursive ) Vec_PtrPush( vNodes, pRoot ); } @@ -428,14 +419,14 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager pNodeC = Abc_ObjFanin( pNode, iVar ); // get the negative cofactor - pNode1 = Abc_NtkCloneObj( pNode ); + pNode1 = Abc_NodeClone( 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 = Abc_NodeClone( pNode ); pNode2->pData = Cudd_Cofactor( dd, pNode->pData, dd->vars[iVar] ); Cudd_Ref( pNode2->pData ); Abc_NodeMinimumBase( pNode2 ); if ( Abc_NodeIsForDsd(pNode2) ) @@ -455,7 +446,7 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager /**Function************************************************************* - Synopsis [Checks if the node should be decomposed by DSD.] + Synopsis [Performs decomposition of one node.] Description [] @@ -467,14 +458,12 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ) { DdManager * dd = pNode->pNtk->pManFunc; -// DdNode * bFunc, * bFunc0, * bFunc1; + 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) ); @@ -486,9 +475,6 @@ bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ) else return 1; } -*/ - if ( Abc_ObjFaninNum(pNode) > 2 ) - return 1; return 0; } 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 index 3bc9fbed..55ae23ff 100644 --- a/src/base/abci/abcFpga.c +++ b/src/base/abci/abcFpga.c @@ -25,12 +25,12 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ); +static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -44,7 +44,7 @@ static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNo SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ) +Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fVerbose ) { int fShowSwitching = 1; Abc_Ntk_t * pNtkNew; @@ -68,14 +68,11 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int } // perform FPGA mapping - pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fLatchPaths, fVerbose ); + pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, 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 ); @@ -91,9 +88,6 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int // 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 ) ) { @@ -115,14 +109,13 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int SeeAlso [] ***********************************************************************/ -Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ) +Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, 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) ); @@ -133,17 +126,10 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, 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 ); + Fpga_ManSetInputArrivals( pMan, Abc_NtkGetCiArrivalFloats(pNtk) ); // 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]; @@ -158,6 +144,12 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, Vec_PtrForEachEntry( vNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); + // consider the case of a constant + if ( Abc_NodeIsConst(pNode) ) + { + Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan); + continue; + } // add the node to the mapper pNodeFpga = Fpga_NodeAnd( pMan, Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), @@ -168,7 +160,7 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, if ( pSwitching ) Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); // set up the choice node - if ( Abc_AigNodeIsChoice( pNode ) ) + if ( Abc_NodeIsAigChoice( 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 ); @@ -202,15 +194,15 @@ Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ) Abc_Obj_t * pNode, * pNodeNew; int i, nDupGates; // create the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_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) ); + if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk->pManFunc) ) > 0 ) + Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NodeCreateConst1(pNtkNew) ); // process the nodes in topological order pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) @@ -223,10 +215,6 @@ Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ) 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) ) 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 index be8a25f1..a11e6eef 100644 --- a/src/base/abci/abcFraig.c +++ b/src/base/abci/abcFraig.c @@ -26,19 +26,16 @@ /// 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 ); +extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes ); +static Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ); + +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_Aig_t * pMan, Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -52,30 +49,19 @@ static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) +Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes ) { 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" ); + Fraig_Man_t * pMan; // perform fraiging - pMan = Abc_NtkToFraig( pNtk, pParams, fAllNodes, fExdc ); - // add algebraic choices -// if ( pPars->fChoicing ) -// Fraig_ManAddChoices( pMan, 0, 6 ); + pMan = Abc_NtkToFraig( pNtk, pParams, fAllNodes ); // 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 ); + 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 ) ) { @@ -97,13 +83,13 @@ Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int f SeeAlso [] ***********************************************************************/ -void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) +Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes ) { - int fInternal = ((Fraig_Params_t *)pParams)->fInternal; Fraig_Man_t * pMan; ProgressBar * pProgress; + Fraig_Node_t * pNodeFraig; Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; + Abc_Obj_t * pNode, * pConst1, * pReset; int i; assert( Abc_NtkIsStrash(pNtk) ); @@ -111,35 +97,36 @@ void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExd // 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_NtkCleanCopy( pNtk ); Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, i); - + pConst1 = Abc_AigConst1( pNtk->pManFunc ); + pReset = Abc_AigReset( pNtk->pManFunc ); + // perform strashing vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 ); - if ( !fInternal ) + if ( !pParams->fInternal ) pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( vNodes, pNode, i ) { - if ( Abc_ObjFaninNum(pNode) == 0 ) - continue; - if ( !fInternal ) + if ( !pParams->fInternal ) Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNode->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, + if ( pNode == pConst1 ) + pNodeFraig = Fraig_ManReadConst1(pMan); + else if ( pNode == pReset ) + continue; + else + pNodeFraig = Fraig_NodeAnd( pMan, Fraig_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), Fraig_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + assert( pNode->pCopy == NULL ); + pNode->pCopy = (Abc_Obj_t *)pNodeFraig; } - if ( !fInternal ) + if ( !pParams->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) ) ); @@ -148,123 +135,7 @@ void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExd /**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.] + Synopsis [Transforms FRAIG into what looks like a strashed network.] Description [] @@ -275,27 +146,26 @@ void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) { - ProgressBar * pProgress; +// 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 ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_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) ); + Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew->pManFunc) ); // process the nodes in topological order - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); +// pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { - Extra_ProgressBarUpdate( pProgress, i, NULL ); +// 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 ); +// Extra_ProgressBarStop( pProgress ); return pNtkNew; } @@ -362,109 +232,6 @@ Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFrai 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) ); -} @@ -496,10 +263,9 @@ Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ) } // perform strashing - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_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 ) ); @@ -556,6 +322,7 @@ int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ) void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { ProgressBar * pProgress; + Abc_Aig_t * pMan = pNtkNew->pManFunc; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pNodeNew, * pObj; int i; @@ -569,7 +336,7 @@ void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) // get the node assert( Abc_ObjIsNode(pNode) ); // strash the node - pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode ); + pNodeNew = Abc_NodeFraigTrust( pMan, pNode ); // get the old object if ( Abc_NtkIsNetlist(pNtk) ) pObj = Abc_ObjFanout0( pNode ); // the fanout net @@ -595,9 +362,10 @@ void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) +Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) { Abc_Obj_t * pSum, * pFanin; + Abc_Obj_t * pConst1 = Abc_AigConst1(pMan); void ** ppTail; int i, nFanins, fCompl; @@ -607,11 +375,11 @@ Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * 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) ); + return Abc_ObjNotCond( pConst1, 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, + return Abc_AigAnd( pMan, 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) ); @@ -648,32 +416,49 @@ Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ -int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd ) +int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ) { - Vec_Ptr_t * vStore; - Abc_Ntk_t * pNtk; - // create the network to be stored - pNtk = Abc_NtkStrash( pNtkAdd, 0, 0, 0 ); - if ( pNtk == NULL ) + extern int Abc_NtkAppendNew( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); + + Abc_Ntk_t * pStore; + int nAndsOld; + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) { - printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" ); + printf( "The netlist need to be converted into a logic network before adding it to storage.\n" ); return 0; } + // get the network currently stored - vStore = Abc_FrameReadStore(); - if ( Vec_PtrSize(vStore) > 0 ) + pStore = Abc_FrameReadNtkStore(); + if ( pStore == NULL ) { - // 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 ) ) + // start the stored network + pStore = Abc_NtkStrash( pNtk, 0, 0 ); + if ( pStore == NULL ) { - 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(); + printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" ); + return 0; } + // save the parameters + Abc_FrameSetNtkStore( pStore ); + Abc_FrameSetNtkStoreSize( 1 ); + nAndsOld = 0; } - Vec_PtrPush( vStore, pNtk ); -// printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) ); + else + { + // add the new network to storage + nAndsOld = Abc_NtkNodeNum( pStore ); +// if ( !Abc_NtkAppend( pStore, pNtk ) ) + if ( !Abc_NtkAppendNew( pStore, pNtk ) ) + { + printf( "The current network cannot be appended to the stored network.\n" ); + return 0; + } + // set the number of networks stored + Abc_FrameSetNtkStoreSize( Abc_FrameReadNtkStoreSize() + 1 ); + } + printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pStore) - nAndsOld ); return 1; } @@ -690,54 +475,56 @@ int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd ) ***********************************************************************/ Abc_Ntk_t * Abc_NtkFraigRestore() { - extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ); + extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Abc_Ntk_t * pNtk, void * pParams ); + Fraig_Params_t Params; - Vec_Ptr_t * vStore; - Abc_Ntk_t * pNtk, * pFraig; + Abc_Ntk_t * pStore, * pFraig; int nWords1, nWords2, nWordsMin; int clk = clock(); // get the stored network - vStore = Abc_FrameReadStore(); - if ( Vec_PtrSize(vStore) == 0 ) + pStore = Abc_FrameReadNtkStore(); + Abc_FrameSetNtkStore( NULL ); + if ( pStore == NULL ) { 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 ); + printf( "Currently stored %d networks with %d nodes will be fraiged.\n", + Abc_FrameReadNtkStoreSize(), Abc_NtkNodeNum(pStore) ); // 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)); + nWords2 = (1<<27) / (Abc_NtkNodeNum(pStore) + Abc_NtkCiNum(pStore)); 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 ); + 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 = 99; // the max number of backtracks to perform + Params.nBTLimit = 1000000; // 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 + Params.fInternal = 1; // the flag indicates the internal run + +// Fraig_ManReportChoices( p ); + // transform it into FRAIG +// pFraig = Abc_NtkFraig( pStore, &Params, 1 ); + pFraig = Abc_NtkFraigPartitioned( pStore, &Params ); + +PRT( "Total fraiging time", clock() - clk ); + if ( pFraig == NULL ) + return NULL; + Abc_NtkDelete( pStore ); return pFraig; } @@ -754,13 +541,12 @@ Abc_Ntk_t * Abc_NtkFraigRestore() ***********************************************************************/ 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 ); + Abc_Ntk_t * pStore; + // get the stored network + pStore = Abc_FrameReadNtkStore(); + if ( pStore ) + Abc_NtkDelete( pStore ); + Abc_FrameSetNtkStore( NULL ); } /**Function************************************************************* @@ -781,7 +567,7 @@ void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig ) int i, k; // check that the PO functions are correct nPoFinal = Abc_NtkPoNum(pFraig); - nStored = Abc_FrameReadStoreSize(); + nStored = Abc_FrameReadNtkStoreSize(Abc_FrameGetGlobalFrame()); assert( nPoFinal % nStored == 0 ); nPoOrig = nPoFinal / nStored; for ( i = 0; i < nPoOrig; i++ ) diff --git a/src/base/abci/abcFxu.c b/src/base/abci/abcFxu.c index 45515dd1..3a70862f 100644 --- a/src/base/abci/abcFxu.c +++ b/src/base/abci/abcFxu.c @@ -30,7 +30,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// @@ -53,19 +53,16 @@ static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); 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) ) + // convert nodes to SOPs + if ( Abc_NtkIsMappedLogic(pNtk) ) + Abc_NtkUnmap(pNtk); + else if ( Abc_NtkIsBddLogic(pNtk) ) + Abc_NtkBddToSop(pNtk); + else { // 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) ) { @@ -111,7 +108,7 @@ bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ) { Abc_ObjForEachFanin( pNode, pFanin1, i ) { - if ( i < 2 && Abc_ObjFaninC(pNode, i) ) + if ( Abc_ObjFaninC(pNode, i) ) return 0; Abc_ObjForEachFanin( pNode, pFanin2, k ) { 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 index d3513bbe..a4731095 100644 --- a/src/base/abci/abcHaig.c +++ b/src/base/abci/abcHaig.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "abc.h" +#include "hop.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -28,127 +29,6 @@ /// 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.] @@ -467,10 +347,10 @@ Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p ) assert( p->nCreated == Vec_PtrSize(p->vObjs) ); // start the new network - pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG ); // transfer new nodes to the PIs of HOP - Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig ); + Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig->pManFunc ); Hop_ManForEachPi( p, pObj, i ) pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i ); @@ -636,59 +516,6 @@ int Abc_NtkHaigResetReprs( Hop_Man_t * p ) 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************************************************************* 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 a470448e..00000000 --- a/src/base/abci/abcIvy.c +++ /dev/null @@ -1,1105 +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 ) - { -// int clk = clock(); -//printf( "Before rwsat = %d. ", Abc_NtkNodeNum(pNtk) ); - 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 ); -//printf( "After rwsat = %d. ", Abc_NtkNodeNum(pNtk) ); -//PRT( "Time", clock() - clk ); - } - - // 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 index d4d50923..ec5352cb 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -40,7 +40,7 @@ static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Sup //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -56,28 +56,28 @@ static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Sup ***********************************************************************/ 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 fShowSwitching = 0; int clk; assert( Abc_NtkIsStrash(pNtk) ); // check that the library is available - if ( Abc_FrameReadLibGen() == NULL ) + if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == NULL ) { printf( "The current library is not available.\n" ); return 0; } // derive the supergate library - if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) + if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL && Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) ) { printf( "A simple supergate library is derived from gate library \"%s\".\n", - Mio_LibraryReadName(Abc_FrameReadLibGen()) ); - Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); + Mio_LibraryReadName(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) ); + Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) ); } // print a warning about choice nodes @@ -113,9 +113,6 @@ clk = clock(); return NULL; Map_ManFree( pMan ); - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { @@ -159,7 +156,6 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f // 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]; @@ -174,6 +170,12 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f Vec_PtrForEachEntry( vNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); + // consider the case of a constant + if ( Abc_NodeIsConst(pNode) ) + { + Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan); + continue; + } // add the node to the mapper pNodeMap = Map_NodeAnd( pMan, Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), @@ -184,7 +186,7 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f if ( pSwitching ) Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); // set up the choice node - if ( Abc_AigNodeIsChoice( pNode ) ) + if ( Abc_NodeIsAigChoice( 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 ); @@ -218,12 +220,17 @@ Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) 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 ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_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 ); + // set the constant node + if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk->pManFunc) ) > 0 ) + Map_NodeSetData( Map_ManReadConst1(pMan), 1, (char *)Abc_NodeCreateConst1(pNtkNew) ); + // assign the mapping of the required phase to the POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) @@ -257,10 +264,6 @@ Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int { 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 ) @@ -369,7 +372,7 @@ Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap * (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); + return Abc_NodeCreateConst0(pNtkNew); } } @@ -388,6 +391,38 @@ Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap } +/**Function************************************************************* + + Synopsis [Unmaps the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkUnmap( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + char * pSop; + int i; + + assert( Abc_NtkIsMappedLogic(pNtk) ); + // update the functionality manager + assert( pNtk->pManFunc == Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) ); + 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; +} + @@ -411,18 +446,18 @@ Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ) assert( Abc_NtkIsStrash(pNtk) ); // check that the library is available - if ( Abc_FrameReadLibGen() == NULL ) + if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == NULL ) { printf( "The current library is not available.\n" ); return 0; } // derive the supergate library - if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) + if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL && Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) ) { printf( "A simple supergate library is derived from gate library \"%s\".\n", - Mio_LibraryReadName(Abc_FrameReadLibGen()) ); - Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); + Mio_LibraryReadName(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) ); + Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) ); } // print a warning about choice nodes @@ -469,7 +504,6 @@ Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ) ***********************************************************************/ 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; @@ -485,12 +519,8 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) // 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; - } + pNtkNew = Abc_NtkRenode( pNtkNew2, 0, 20, 0, 0, 1 ); + Abc_NtkBddToSop( pNtkNew ); // set the old network to point to the new network Abc_NtkForEachCi( pNtk, pNode, i ) @@ -504,14 +534,14 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) // 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], 0, (char *)Abc_NodeCreateInv(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) ); + if ( Abc_NodeIsConst(pNode) ) + continue; + Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NodeCreateInv(pNtkNew,pNode->pCopy) ); Map_NodeSetData( (Map_Node_t *)pNode->pNext, 1, (char *)pNode->pCopy ); } @@ -520,8 +550,8 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); -// if ( Abc_NodeIsConst(pNode) ) -// continue; + if ( Abc_NodeIsConst(pNode) ) + continue; Abc_NodeSuperChoice( pNtkNew, pNode ); } Extra_ProgressBarStop( pProgress ); @@ -631,7 +661,7 @@ Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * p * (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); + return Abc_NodeCreateConst0(pNtkNew); } } 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 index 257d930f..1e728d92 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -24,19 +24,16 @@ /// 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 Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb ); 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 ); +static void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode ); +static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb ); +static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame, Vec_Ptr_t * vNodes ); -// 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -50,20 +47,18 @@ static void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, i SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ) +Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) { 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 ) ) + if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 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)); + fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0)); + fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0)); if ( pNtk1 && pNtk2 ) - pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize ); + pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb ); if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); return pTemp; @@ -80,24 +75,24 @@ Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int n SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ) +Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) { - char Buffer[1000]; + char Buffer[100]; 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 ); + pNtkMiter = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG ); sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); - pNtkMiter->pName = Extra_UtilStrsav(Buffer); + pNtkMiter->pName = util_strsav(Buffer); // perform strashing - Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); + Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb ); Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); - Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); + Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb ); Abc_AigCleanup(pNtkMiter->pManFunc); // make sure that everything is okay @@ -121,16 +116,13 @@ Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, in SeeAlso [] ***********************************************************************/ -void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ) +void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb ) { 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 @@ -142,15 +134,12 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk 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 ); + Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObj) ); } + // create the only PO + pObjNew = Abc_NtkCreatePo( pNtkMiter ); + // add the PO name + Abc_NtkLogicStoreName( pObjNew, "miter" ); } else { @@ -163,31 +152,28 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk 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 ); + Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObj) ); } + // create the only PO + pObjNew = Abc_NtkCreatePo( pNtkMiter ); + // add the PO name + Abc_NtkLogicStoreName( pObjNew, "miter" ); // 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" ); + pObjNew = Abc_NtkDupObj( pNtkMiter, pObj ); + Vec_PtrPush( pNtkMiter->vCis, pObjNew ); + Vec_PtrPush( pNtkMiter->vCos, pObjNew ); + // add name + Abc_NtkLogicStoreNamePlus( pObjNew, Abc_ObjName(pObj), "_1" ); } Abc_NtkForEachLatch( pNtk2, pObj, i ) { - pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); + pObjNew = Abc_NtkDupObj( pNtkMiter, pObj ); + Vec_PtrPush( pNtkMiter->vCis, pObjNew ); + Vec_PtrPush( pNtkMiter->vCos, pObjNew ); // 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" ); + Abc_NtkLogicStoreNamePlus( pObjNew, Abc_ObjName(pObj), "_2" ); } } } @@ -205,11 +191,26 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk ***********************************************************************/ void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ) { - Abc_Obj_t * pNode; + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pConst1, * pConst1New; int i; - assert( Abc_NtkIsDfsOrdered(pNtk) ); - Abc_AigForEachAnd( pNtk, pNode, i ) - pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + // get the constant nodes + pConst1 = Abc_AigConst1( pNtk->pManFunc ); + pConst1New = Abc_AigConst1( pNtkMiter->pManFunc ); + // perform strashing + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( pNode == pConst1 ) + pNode->pCopy = pConst1New; + else + pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + } + Vec_PtrFree( vNodes ); + Extra_ProgressBarStop( pProgress ); } /**Function************************************************************* @@ -226,15 +227,22 @@ void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ) void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot ) { Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; + Abc_Obj_t * pNode, * pNodeNew, * pConst1, * pConst1New; int i; - // map the constant nodes - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter); + // get the constant nodes + pConst1 = Abc_AigConst1( pNtk->pManFunc ); + pConst1New = Abc_AigConst1( pNtkMiter->pManFunc ); // 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) ); + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNode = vNodes->pArray[i]; + if ( pNode == pConst1 ) + pNodeNew = pConst1New; + else + pNodeNew = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + pNode->pCopy = pNodeNew; + } Vec_PtrFree( vNodes ); } @@ -250,7 +258,7 @@ void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * p SeeAlso [] ***********************************************************************/ -void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ) +void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb ) { Vec_Ptr_t * vPairs; Abc_Obj_t * pMiter, * pNode; @@ -278,184 +286,19 @@ void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNt } // connect new latches Abc_NtkForEachLatch( pNtk1, pNode, i ) - Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); + Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); Abc_NtkForEachLatch( pNtk2, pNode, i ) - Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); + Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(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 ); + pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairs ); 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; + Vec_PtrFree( vPairs ); } -/**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.] @@ -469,7 +312,7 @@ Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ) { - char Buffer[1000]; + char Buffer[100]; Abc_Ntk_t * pNtkMiter; Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; @@ -477,22 +320,21 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In 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 ); + pNtkMiter = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG ); sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) ); - pNtkMiter->pName = Extra_UtilStrsav(Buffer); + pNtkMiter->pName = util_strsav(Buffer); // get the root output pRoot = Abc_NtkCo( pNtk, Out ); // perform strashing - Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); + Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1 ); // set the first cofactor - Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter->pManFunc) ); if ( In2 >= 0 ) - Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter); + Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1( pNtkMiter->pManFunc ); // add the first cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); @@ -500,9 +342,9 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; // set the second cofactor - Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter); + Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1( pNtkMiter->pManFunc ); if ( In2 >= 0 ) - Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter->pManFunc) ); // add the second cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); @@ -524,98 +366,6 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In } -/**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; -} - @@ -623,8 +373,8 @@ Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ) 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 + Description [Return 1 if the miter is sat for at least one output. + Return 0 if the miter is unsat for all its outputs. Returns -1 if the miter is undecided for some outputs.] SideEffects [] @@ -639,31 +389,23 @@ int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ) assert( Abc_NtkIsStrash(pMiter) ); Abc_NtkForEachPo( pMiter, pNodePo, i ) { - pChild = Abc_ObjChild0( pNodePo ); - // check if the output is constant 1 - if ( Abc_AigNodeIsConst(pChild) ) + pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) ); + if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) ) { - assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) ); + assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter->pManFunc) ); if ( !Abc_ObjIsComplement(pChild) ) { // if the miter is constant 1, return immediately -// printf( "MITER IS CONSTANT 1!\n" ); - return 0; + printf( "MITER IS CONSTANT 1!\n" ); + return 1; } } -/* - // check if the output is not constant 0 - else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) ) - { - return 0; - } -*/ // if the miter is undecided (or satisfiable), return immediately else return -1; } - // return 1, meaning all outputs are constant zero - return 1; + // return 0, meaning all outputs are constant zero + return 0; } /**Function************************************************************* @@ -684,7 +426,7 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ) if ( Abc_NtkPoNum(pMiter) == 1 ) { pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) ); - if ( Abc_AigNodeIsConst(pChild) ) + if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) ) { if ( Abc_ObjIsComplement(pChild) ) printf( "Unsatisfiable.\n" ); @@ -700,7 +442,7 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ) { pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) ); printf( "Output #%2d : ", i ); - if ( Abc_AigNodeIsConst(pChild) ) + if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) ) { if ( Abc_ObjIsComplement(pChild) ) printf( "Unsatisfiable.\n" ); @@ -727,158 +469,23 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ) ***********************************************************************/ 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]; + char Buffer[100]; 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) ); + assert( Abc_NtkIsStrash(pNtk) ); // start the new network - pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkFrames = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG ); sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); - pNtkFrames->pName = Extra_UtilStrsav(Buffer); + pNtkFrames->pName = util_strsav(Buffer); // create new latches (or their initial values) and remember them in the new latches if ( !fInitial ) { - Abc_NtkForEachLatch( pNtk, pLatch, i ) { + Abc_NtkForEachLatch( pNtk, pLatch, i ) Abc_NtkDupObj( pNtkFrames, pLatch ); - if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); - } } else { @@ -888,17 +495,14 @@ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFram 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 ); + Abc_NtkLogicStoreName( pLatch->pCopy, Abc_ObjName(pLatch) ); Counter++; } - else { - pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); - } - - if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); + else + pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames->pManFunc), Abc_LatchIsInit0(pLatch) ); } if ( Counter ) - printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); + printf( "Warning: %d uninitialized latches are replaced by free variables.\n", Counter ); } // create the timeframes @@ -907,7 +511,7 @@ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFram for ( i = 0; i < nFrames; i++ ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); - Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg ); + Abc_NtkAddFrame( pNtkFrames, pNtk, i, vNodes ); } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); @@ -917,20 +521,13 @@ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFram { Abc_NtkForEachLatch( pNtk, pLatch, i ) { - pLatchNew = Abc_NtkBox(pNtkFrames, i); - Abc_ObjAddFanin( pLatchNew, pLatch->pCopy ); - Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL ); + pLatchNew = Abc_NtkLatch(pNtkFrames, i); + Abc_ObjAddFanin( pLatchNew, Abc_ObjFanin0(pLatch)->pCopy ); + Vec_PtrPush( pNtkFrames->vCis, pLatchNew ); + Vec_PtrPush( pNtkFrames->vCos, pLatchNew ); + Abc_NtkLogicStoreName( pLatchNew, Abc_ObjName(pLatch) ); } } - 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 ) ) { @@ -939,8 +536,6 @@ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFram return NULL; } return pNtkFrames; -*/ - return NULL; } /**Function************************************************************* @@ -957,24 +552,22 @@ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFram SeeAlso [] ***********************************************************************/ -void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ) +void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes ) { -/* 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); + pConst1 = Abc_AigConst1( pNtk->pManFunc ); + pConst1New = Abc_AigConst1( pNtkFrames->pManFunc ); // 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); + Abc_NtkLogicStoreNamePlus( pNodeNew, Abc_ObjName(pNode), Buffer ); } // add the internal nodes Vec_PtrForEachEntry( vNodes, pNode, i ) @@ -984,160 +577,19 @@ void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec 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); + Abc_NtkLogicStoreNamePlus( pNodeNew, Abc_ObjName(pNode), Buffer ); } // 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; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pCopy = Abc_ObjChild0Copy(pLatch); } -/**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 index f127811e..6362a925 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -25,12 +25,12 @@ //////////////////////////////////////////////////////////////////////// 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( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pConst1 ); 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 ); +static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -78,13 +78,13 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo return NULL; // start the network - pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); - pNtk->pName = Extra_UtilStrsav(pNamePo); + pNtk = Abc_NtkAlloc( ABC_TYPE_LOGIC, ABC_FUNC_BDD ); + pNtk->pName = util_strsav(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 ); + Abc_NtkLogicStoreName( Abc_NtkCreatePi(pNtk), pName ); // create the node pNode = Abc_NtkCreateNode( pNtk ); pNode->pData = Cudd_bddTransfer( dd, pNtk->pManFunc, bFunc ); Cudd_Ref(pNode->pData); @@ -93,7 +93,7 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo // create the only PO pNodePo = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pNodePo, pNode ); - Abc_ObjAssignName( pNodePo, pNamePo, NULL ); + Abc_NtkLogicStoreName( pNodePo, pNamePo ); // make the network minimum base Abc_NtkMinimumBase( pNtk ); if ( vNamesPiFake ) @@ -121,7 +121,7 @@ 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 ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP ); Abc_NtkBddToMuxesPerform( pNtk, pNtkNew ); Abc_NtkFinalize( pNtk, pNtkNew ); // make sure everything is okay @@ -148,9 +148,12 @@ Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ) void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { ProgressBar * pProgress; - Abc_Obj_t * pNode, * pNodeNew; + DdManager * dd = pNtk->pManFunc; + Abc_Obj_t * pNode, * pNodeNew, * pConst1; Vec_Ptr_t * vNodes; int i; + // create the constant one node + pConst1 = Abc_NodeCreateConst1( pNtkNew ); // perform conversion in the topological order vNodes = Abc_NtkDfs( pNtk, 0 ); pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); @@ -159,7 +162,7 @@ void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) Extra_ProgressBarUpdate( pProgress, i, NULL ); // convert one node assert( Abc_ObjIsNode(pNode) ); - pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew ); + pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew, pConst1 ); // mark the old node with the new one assert( pNode->pCopy == NULL ); pNode->pCopy = pNodeNew; @@ -179,7 +182,7 @@ void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ) +Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pConst1 ) { DdManager * dd = pNodeOld->pNtk->pManFunc; DdNode * bFunc = pNodeOld->pData; @@ -189,13 +192,14 @@ Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ) // 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 + st_insert( tBdd2Node, (char *)b1, (char *)pConst1 ); 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 ); + pNodeNew = Abc_NodeCreateInv( pNtkNew, pNodeNew ); return pNodeNew; } @@ -214,19 +218,17 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * { 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 ); + pNodeNew0 = Abc_NodeCreateInv( 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 ); + pNodeNew = Abc_NodeCreateMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 ); st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew ); return pNodeNew; } @@ -243,96 +245,88 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * SeeAlso [] ***********************************************************************/ -DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) +DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly ) { + int fReorder = 1; ProgressBar * pProgress; - Abc_Obj_t * pObj, * pFanin; - Vec_Att_t * pAttMan; - DdManager * dd; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pNode; DdNode * bFunc; - int i, k, Counter; - - // remove dangling nodes - Abc_AigCleanup( pNtk->pManFunc ); + DdManager * dd; + int i; // start the manager - assert( Abc_NtkGlobalBdd(pNtk) == NULL ); + assert( pNtk->pManGlob == 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 ); + // set the elementary variables + Abc_NtkCleanCopy( pNtk ); + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)dd->vars[i]; // assign the constant node BDD - pObj = Abc_AigConst1(pNtk); - if ( Abc_ObjFanoutNum(pObj) > 0 ) + pNode = Abc_AigConst1( pNtk->pManFunc ); + pNode->pCopy = (Abc_Obj_t *)dd->one; Cudd_Ref( dd->one ); + + // collect the global functions of the COs + vFuncsGlob = Vec_PtrAlloc( 100 ); + if ( fLatchOnly ) { - bFunc = dd->one; - Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); - } - // set the elementary variables - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) + // construct the BDDs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pNode, i ) { - bFunc = dd->vars[i]; -// bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i]; - Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); + Extra_ProgressBarUpdate( pProgress, i, NULL ); + bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode) ); + if ( bFunc == NULL ) + { + printf( "Constructing global BDDs timed out.\n" ); + Extra_ProgressBarStop( pProgress ); + Cudd_Quit( dd ); + return NULL; + } + bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); Cudd_Ref( bFunc ); + Vec_PtrPush( vFuncsGlob, 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 ) + Extra_ProgressBarStop( pProgress ); + } + else { - bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); - if ( bFunc == NULL ) + // construct the BDDs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) { - if ( fVerbose ) - printf( "Constructing global BDDs is aborted.\n" ); - Abc_NtkFreeGlobalBdds( pNtk, 0 ); - Cudd_Quit( dd ); - return NULL; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode) ); + if ( bFunc == NULL ) + { + printf( "Constructing global BDDs timed out.\n" ); + Extra_ProgressBarStop( pProgress ); + Cudd_Quit( dd ); + return NULL; + } + bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); Cudd_Ref( bFunc ); + Vec_PtrPush( vFuncsGlob, bFunc ); } - bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); - Abc_ObjSetGlobalBdd( pObj, bFunc ); + Extra_ProgressBarStop( pProgress ); } - Extra_ProgressBarStop( pProgress ); -/* // derefence the intermediate BDDs - Abc_NtkForEachNode( pNtk, pObj, i ) - if ( pObj->pCopy ) + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) { - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pCopy ); - pObj->pCopy = NULL; + Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); + pNode->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 ); + pNtk->pManGlob = dd; + pNtk->vFuncsGlob = vFuncsGlob; return dd; } @@ -347,107 +341,39 @@ DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDrop SeeAlso [] ***********************************************************************/ -DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) +DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode ) { - DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC; - int fDetectMuxes = 1; + DdNode * bFunc, * bFunc0, * bFunc1; 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 ); + if ( Cudd_ReadKeys(dd) > 500000 ) 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 ); - } + if ( pNode->pCopy ) + return (DdNode *)pNode->pCopy; + // compute the result for both branches + bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0) ); + if ( bFunc0 == NULL ) + return NULL; + Cudd_Ref( bFunc0 ); + bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1) ); + 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 ); + // set the result + assert( pNode->pCopy == NULL ); + pNode->pCopy = (Abc_Obj_t *)bFunc; return bFunc; } /**Function************************************************************* - Synopsis [Frees the global BDDs of the network.] + Synopsis [Dereferences global BDDs of the network.] Description [] @@ -456,123 +382,16 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSize 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 ) +void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk ) { - /* - 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 ); + assert( pNtk->pManGlob ); + assert( pNtk->vFuncsGlob ); + Vec_PtrForEachEntry( pNtk->vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( pNtk->pManGlob, bFunc ); + Vec_PtrFree( pNtk->vFuncsGlob ); + pNtk->vFuncsGlob = NULL; } //////////////////////////////////////////////////////////////////////// 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 index 85c4e918..506010c7 100644 --- a/src/base/abci/abcPart.c +++ b/src/base/abci/abcPart.c @@ -19,87 +19,77 @@ ***********************************************************************/ #include "abc.h" +#include "hop.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.] + Synopsis [Returns the number of common entries.] - Description [] + Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ -Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize ) +static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) { - 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; + int i, k, Counter = 0; + for ( i = k = 0; i < Vec_IntSize(vArr1) && k < Vec_IntSize(vArr2); ) + { + if ( Vec_IntEntry(vArr1,i) == Vec_IntEntry(vArr2,k) ) + Counter++, i++, k++; + else if ( Vec_IntEntry(vArr1,i) < Vec_IntEntry(vArr2,k) ) + i++; + else + k++; + } + return Counter; } /**Function************************************************************* - Synopsis [Stops the memory manager.] + Synopsis [Returns the result of merging the two vectors.] - Description [] + Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ -void Supp_ManStop( Supp_Man_t * p ) +static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) { - void * pMemory; - int i; - Vec_PtrForEachEntry( p->vMemory, pMemory, i ) - free( pMemory ); - Vec_PtrFree( p->vMemory ); - Vec_PtrFree( p->vFree ); - free( p ); + Vec_Int_t * vArr; + int i, k; + vArr = Vec_IntAlloc( Vec_IntSize(vArr1) ); + for ( i = k = 0; i < Vec_IntSize(vArr1) && k < Vec_IntSize(vArr2); ) + { + if ( Vec_IntEntry(vArr1,i) == Vec_IntEntry(vArr2,k) ) + Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) ), i++, k++; + else if ( Vec_IntEntry(vArr1,i) < Vec_IntEntry(vArr2,k) ) + Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) ), i++; + else + Vec_IntPush( vArr, Vec_IntEntry(vArr2,k) ), k++; + } + for ( ; i < Vec_IntSize(vArr1); i++ ) + Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) ); + for ( ; k < Vec_IntSize(vArr2); k++ ) + Vec_IntPush( vArr, Vec_IntEntry(vArr2,k) ); + return vArr; } /**Function************************************************************* - Synopsis [Fetches the memory entry of the given size.] + Synopsis [Comparison procedure for two arrays.] Description [] @@ -108,35 +98,18 @@ void Supp_ManStop( Supp_Man_t * p ) SeeAlso [] ***********************************************************************/ -char * Supp_ManFetch( Supp_Man_t * p, int nSize ) +static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) { - 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; + if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) + return -1; + if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) + return 1; + return 0; } /**Function************************************************************* - Synopsis [Recycles the memory entry of the given size.] + Synopsis [Comparison procedure for two integers.] Description [] @@ -145,18 +118,18 @@ char * Supp_ManFetch( Supp_Man_t * p, int nSize ) SeeAlso [] ***********************************************************************/ -void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize ) +static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) { - 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 ); + if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) + return -1; + if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) + return 1; + return 0; } /**Function************************************************************* - Synopsis [Fetches the memory entry of the given size.] + Synopsis [Sorting the entries by their integer value.] Description [] @@ -165,19 +138,19 @@ void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize ) SeeAlso [] ***********************************************************************/ -static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs ) +static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse ) { - 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; + 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 ); } /**Function************************************************************* - Synopsis [Recycles the memory entry of the given size.] + Synopsis [Performs DFS for one node.] Description [] @@ -186,16 +159,31 @@ static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int n SeeAlso [] ***********************************************************************/ -static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry ) +void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { - assert( pEntry->nOuts <= pEntry->nOutsAlloc ); - assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); - Supp_ManRecycle( p, (char *)pEntry, sizeof(Supp_One_t) + sizeof(int) * pEntry->nOutsAlloc ); + 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 [Merges two entries.] + Synopsis [Returns the set of CI nodes in the support of the given nodes.] Description [] @@ -204,37 +192,26 @@ static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry ) SeeAlso [] ***********************************************************************/ -Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs ) +Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) { - 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; + 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 [Tranfers the entry.] + Synopsis [Extra_UtilStrsav()] Description [] @@ -243,19 +220,16 @@ Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t SeeAlso [] ***********************************************************************/ -Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p ) +char * Extra_UtilStrsav( char * s ) { - 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; + if ( s == NULL ) + return s; + return strcpy(ALLOC(char, strlen(s)+1), s); } /**Function************************************************************* - Synopsis [Computes supports of the POs in the multi-output AIG.] + Synopsis [Creates the network composed of several logic cones.] Description [] @@ -264,255 +238,196 @@ Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p ) SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk ) +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, * pNext; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + char Buffer[1000]; 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 ) + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc ); + // 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->pManFunc)->pCopy = Abc_AigConst1(pNtkNew->pManFunc); + + // 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 ) { - // 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 ); - } + if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); +// Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) ); + } } - return vNodes; + + // 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 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + Vec_PtrFree( vNodes ); + + // add the PO corresponding to the 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 ); + Abc_NtkLogicStoreName( pNodeCoNew, Abc_ObjName(pObj) ); + } + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" ); + return pNtkNew; } /**Function************************************************************* - Synopsis [Computes supports of the POs.] + Synopsis [Appends the second network to the first.] - Description [Returns the ptr-vector of int-vectors.] + 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 [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkComputeSupportsSmart( Abc_Ntk_t * pNtk ) +int Abc_NtkAppendNew( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) { - 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 ) +// char * pName; + int i, nNewCis; + // the first network should be an AIG + assert( Abc_NtkIsStrash(pNtk1) ); + assert( Abc_NtkIsStrash(pNtk2) ); + // 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 ); + Abc_AigConst1(pNtk2->pManFunc)->pCopy = Abc_AigConst1(pNtk1->pManFunc); + Abc_NtkForEachCi( pNtk2, pObj, i ) { - if ( Abc_ObjIsNode(pObj) ) +// pName = Abc_ObjName(pObj); +// pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj)); + pObj->pCopy = Abc_NtkCi( pNtk1, i ); + if ( pObj->pCopy == NULL ) { - 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; + pObj->pCopy = Abc_NtkDupObj( pNtk1, pObj ); + nNewCis++; } - 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; - } + } + if ( nNewCis ) + printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis ); + // add pNtk2 to pNtk1 while strashing + Abc_NtkForEachNode( pNtk2, pObj, i ) + { + if ( Abc_ObjFaninNum(pObj) == 0 ) continue; - } - if ( pObj == Abc_AigConst1(pNtk) ) + pObj->pCopy = Abc_AigAnd( pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + // add the COs of the second network + { + Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew; + int fCompl;//, iNodeId; + // OR the choices + Abc_NtkForEachCo( pNtk2, pObj, i ) { - if ( Abc_ObjFanoutNum(pObj) ) - pObj->pCopy = (Abc_Obj_t *)Supp_ManFetchEntry( p, 0, Abc_ObjFanoutNum(pObj) ); - continue; +// iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); +// assert( iNodeId >= 0 ); +// pObjOld = Abc_NtkObj( pNtk1, iNodeId ); + pObjOld = Abc_NtkCo( pNtk1, i ); + + // 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) ); } - 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; + // 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 [Computes supports of the POs using naive method.] + Synopsis [Prepare supports.] - Description [Returns the ptr-vector of int-vectors.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkComputeSupportsNaive( Abc_Ntk_t * pNtk ) +Vec_Ptr_t * Abc_NtkPartitionCollectSupps( 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_IntWriteEntry( vSuppI, k, pTemp->Id ); 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.] @@ -524,9 +439,8 @@ int Abc_NtkSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) SeeAlso [] ***********************************************************************/ -int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nSuppSizeLimit, Vec_Int_t * vOne ) +int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, int nPartSizeLimit, Vec_Int_t * vOne ) { -/* Vec_Int_t * vPartSupp, * vPart; double Attract, Repulse, Cost, CostBest; int i, nCommon, iBest; @@ -534,12 +448,12 @@ int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vParts 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; + vPart = Vec_PtrEntry( vPartsAll, i ); + if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) > nPartSizeLimit ) + continue; if ( nCommon == Vec_IntSize(vOne) ) return i; Attract = 1.0 * nCommon / Vec_IntSize(vOne); @@ -557,49 +471,6 @@ int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vParts 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************************************************************* @@ -627,7 +498,7 @@ void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * if ( i == Vec_PtrSize(vPartsAll) - 1 ) break; } -// assert( Counter == Abc_NtkCoNum(pNtk) ); + assert( Counter == Abc_NtkCoNum(pNtk) ); printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) ); } @@ -642,20 +513,20 @@ void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * SeeAlso [] ***********************************************************************/ -void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit ) +void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nPartSizeLimit ) { Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; int i, iPart; - if ( nSuppSizeLimit == 0 ) - nSuppSizeLimit = 200; + if ( nPartSizeLimit == 0 ) + nPartSizeLimit = 200; // pack smaller partitions into larger blocks iPart = 0; vPart = vPartSupp = NULL; Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) { - if ( Vec_IntSize(vOne) < nSuppSizeLimit ) + if ( Vec_IntSize(vOne) < nPartSizeLimit ) { if ( vPartSupp == NULL ) { @@ -671,7 +542,7 @@ void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, Vec_IntFree( vTemp ); Vec_IntFree( Vec_PtrEntry(vPartsAll, i) ); } - if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit ) + if ( Vec_IntSize(vPartSupp) < nPartSizeLimit ) continue; } else @@ -707,49 +578,37 @@ void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, Synopsis [Perform the smart partitioning.] - Description [Returns the ptr-vector of int-vectors.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose ) +Vec_Vec_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose ) { - ProgressBar * pProgress; - Vec_Ptr_t * vPartSuppsChar; - Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll; + Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll, * vPartPtr; Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; - int i, iPart, iOut, clk, clk2, timeFind = 0; + int i, iPart, iOut, clk; // compute the supports for all outputs clk = clock(); -// vSupps = Abc_NtkComputeSupportsNaive( pNtk ); - vSupps = Abc_NtkComputeSupportsSmart( pNtk ); + vSupps = Abc_NtkPartitionCollectSupps( 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; + iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, nPartSizeLimit, vOne ); if ( iPart == -1 ) { // create new partition @@ -760,8 +619,6 @@ timeFind += clock() - clk2; // add this partition and its support Vec_PtrPush( vPartsAll, vPart ); Vec_PtrPush( vPartSuppsAll, vPartSupp ); - - Vec_PtrPush( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) ); } else { @@ -774,22 +631,11 @@ timeFind += clock() - clk2; 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(); @@ -807,20 +653,18 @@ clk = clock(); // compact small partitions // Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); - Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); - + Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nPartSizeLimit ); + if ( fVerbose ) + Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); 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 ) { @@ -830,52 +674,32 @@ PRT( "Comps", clock() - clk ); Vec_IntFree( vPart ); Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); } -*/ - return vPartsAll; + return (Vec_Vec_t *)vPartsAll; } /**Function************************************************************* Synopsis [Perform the naive partitioning.] - Description [Returns the ptr-vector of int-vectors.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize ) +Vec_Vec_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize ) { - Vec_Ptr_t * vParts; + Vec_Vec_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 ); + vParts = Vec_VecStart( nParts ); Abc_NtkForEachCo( pNtk, pObj, i ) - Vec_IntPush( Vec_PtrEntry(vParts, i / nPartSize), i ); + Vec_VecPush( vParts, i / nPartSize, pObj ); 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.] @@ -920,6 +744,7 @@ static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) ); } + /**Function************************************************************* Synopsis [] @@ -956,18 +781,24 @@ Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk ) 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_AigConst1(pNtk->pManFunc)->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 ) +// Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_NtkForEachNode( pNtk, pObj, i ) { + if ( Abc_ObjFaninNum(pObj) == 0 ) + continue; 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 ) +// Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_NtkForEachNode( pNtk, pObj, i ) { + if ( Abc_ObjFaninNum(pObj) == 0 ) + continue; if ( pObj->pCopy ) ((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext; } @@ -980,6 +811,58 @@ Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk ) return pMan; } +/**Function************************************************************* + + Synopsis [Maps terminals of the old networks into those of the new network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPartMapTerminals( Vec_Ptr_t * vParts, Abc_Ntk_t * pNtkOld ) +{ + Abc_Ntk_t * pNtkNew; + stmm_table * tTablePi, * tTablePo; + Abc_Obj_t * pObj, * pTemp; + int i, k; + + // map names into old nodes + tTablePi = stmm_init_table( strcmp, stmm_strhash ); + tTablePo = stmm_init_table( strcmp, stmm_strhash ); + Abc_NtkForEachPi( pNtkOld, pObj, i ) + stmm_insert( tTablePi, Abc_ObjName(pObj), (char *)pObj ); + Abc_NtkForEachPo( pNtkOld, pObj, i ) + stmm_insert( tTablePo, Abc_ObjName(pObj), (char *)pObj ); + + // map new nodes into old nodes + Vec_PtrForEachEntry( vParts, pNtkNew, k ) + { + Abc_NtkForEachPi( pNtkNew, pObj, i ) + { + if ( !stmm_lookup(tTablePi, Abc_ObjName(pObj), (char **)&pTemp) ) + { + printf( "Cannot find PI node %s in the original network.\n", Abc_ObjName(pObj) ); + return; + } + pObj->pCopy = pTemp; + } + Abc_NtkForEachPo( pNtkNew, pObj, i ) + { + if ( !stmm_lookup(tTablePo, Abc_ObjName(pObj), (char **)&pTemp) ) + { + printf( "Cannot find PO node %s in the original network.\n", Abc_ObjName(pObj) ); + return; + } + pObj->pCopy = pTemp; + } + } + stmm_free_table( tTablePi ); + stmm_free_table( tTablePo ); +} + /**Function************************************************************* Synopsis [Stitches together several networks with choice nodes.] @@ -996,23 +879,36 @@ 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; + Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin; - int i, k, iNodeId; + int i, k; // start a new network similar to the original one assert( Abc_NtkIsStrash(pNtk) ); - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG ); + // annotate parts to point to the new network Vec_PtrForEachEntry( vParts, pNtkTemp, i ) { assert( Abc_NtkIsStrash(pNtkTemp) ); Abc_NtkCleanCopy( pNtkTemp ); + } + + // perform mapping of terminals + Abc_NtkPartMapTerminals( vParts, pNtkNew ); + + + // 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_AigConst1(pNtkTemp->pManFunc)->pCopy = Abc_AigConst1(pNtkNew->pManFunc); +/* Abc_NtkForEachCi( pNtkTemp, pObj, k ) { iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); @@ -1023,14 +919,16 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts ) } pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); } - +*/ // add the internal nodes while saving representatives vNodes = Abc_AigDfs( pNtkTemp, 1, 0 ); Vec_PtrForEachEntry( vNodes, pObj, k ) { + if ( Abc_ObjFaninNum(pObj) == 0 ) + continue; pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); assert( !Abc_ObjIsComplement(pObj->pCopy) ); - if ( Abc_AigNodeIsChoice(pObj) ) + if ( Abc_NodeIsAigChoice(pObj) ) for ( pFanin = pObj->pData; pFanin; pFanin = pFanin->pData ) pFanin->pCopy->pCopy = pObj->pCopy; } @@ -1039,6 +937,7 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts ) // 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 ) { @@ -1046,23 +945,11 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts ) 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 ); @@ -1090,112 +977,49 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts ) 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 ) +Abc_Ntk_t * Abc_NtkFraigPartitioned( 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; + Vec_Vec_t * vParts; + Vec_Ptr_t * vFraigs, * 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 ); + vParts = Abc_NtkPartitionSmart( pNtk, 0, 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 ) + vFraigs = Vec_PtrAlloc( Vec_VecSize(vParts) ); + Vec_VecForEachLevel( vParts, vOne, i ) { - Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); - pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); - pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0, 0 ); + pNtkAig = Abc_NtkCreateConeArray( pNtk, vOne, 0 ); + pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0 ); Vec_PtrPush( vFraigs, pNtkFraig ); Abc_NtkDelete( pNtkAig ); - printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); + printf( "Finished part %d (out of %d)\r", i+1, Vec_VecSize(vParts) ); } - Vec_VecFree( (Vec_Vec_t *)vParts ); + Vec_VecFree( vParts ); + printf( " \r" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); // derive the final network + pNtkFraig = Abc_NtkPartStitchChoices( pNtk, vFraigs ); Vec_PtrForEachEntry( vFraigs, pNtkAig, i ) + { +// Abc_NtkPrintStats( stdout, pNtkAig, 0 ); Abc_NtkDelete( pNtkAig ); + } Vec_PtrFree( vFraigs ); - Vec_PtrFree( vOnePtr ); - PRT( "Partitioned fraiging time", clock() - clk ); + + return pNtkFraig; } //////////////////////////////////////////////////////////////////////// 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 index 4003a6d6..41b9288e 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -20,24 +20,13 @@ #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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -55,171 +44,57 @@ 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 = %5d/%5d/%5d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkAssertNum(pNtk) ); + fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); + + if ( !Abc_NtkIsSeq(pNtk) ) + fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) ); else - fprintf( pFile, " i/o = %5d/%5d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); - fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) ); + fprintf( pFile, " lat = %4d", Abc_NtkSeqLatchNum(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) ); + fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(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 if ( Abc_NtkIsSeq(pNtk) ) + fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) ); else - { fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); - fprintf( pFile, " edge = %6d", Abc_NtkGetTotalFanins(pNtk) ); - } - if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) ) - { - } - else if ( Abc_NtkHasSop(pNtk) ) + 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) ); + 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) ) + else if ( !Abc_NtkHasAig(pNtk) ) { assert( 0 ); } if ( Abc_NtkIsStrash(pNtk) ) - fprintf( pFile, " lev = %3d", Abc_AigLevel(pNtk) ); - else - fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) ); + fprintf( pFile, " lev = %3d", Abc_AigGetLevelNum(pNtk) ); + else if ( !Abc_NtkIsSeq(pNtk) ) + fprintf( pFile, " lev = %3d", Abc_NtkGetLevelNum(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************************************************************* @@ -241,7 +116,6 @@ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ) 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) ); @@ -251,8 +125,7 @@ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ) 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, " %s", Abc_ObjName(pObj) ); fprintf( pFile, "\n" ); } @@ -271,38 +144,34 @@ void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pLatch, * pFanin; int i, Counter0, Counter1, Counter2; - int InitNums[4], Init; + int Init0, Init1, Init2; - 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; + assert( !Abc_NtkIsNetlist(pNtk) ); + + Init0 = Init1 = Init2 = 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; - } + if ( Abc_LatchIsInit0(pLatch) ) + Init0++; + else if ( Abc_LatchIsInit1(pLatch) ) + Init1++; + else if ( Abc_LatchIsInitDc(pLatch) ) + Init2++; else assert( 0 ); + pFanin = Abc_ObjFanin0(pLatch); + if ( !Abc_ObjIsNode(pFanin) || !Abc_NodeIsConst(pFanin) ) + continue; + // the latch input is a constant node Counter0++; if ( Abc_LatchIsInitDc(pLatch) ) @@ -318,15 +187,18 @@ void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ) } else { - if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) ) + if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(pLatch) ) Counter2++; } } +// fprintf( pFile, "%-15s: ", pNtk->pName ); +// fprintf( pFile, "L = %5d: 0 = %4d. 1 = %3d. DC = %4d. ", Abc_NtkLatchNum(pNtk), Init0, Init1, Init2 ); +// fprintf( pFile, "Con = %3d. DC = %3d. Mat = %3d. ", Counter0, Counter1, Counter2 ); +// fprintf( pFile, "SFeed = %2d.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); 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) ); + fprintf( pFile, "Lat = %5d: 0 = %4d. 1 = %3d. DC = %4d. \n", Abc_NtkLatchNum(pNtk), Init0, Init1, Init2 ); + fprintf( pFile, "Con = %3d. DC = %3d. Mat = %3d. ", Counter0, Counter1, Counter2 ); + fprintf( pFile, "SFeed = %2d.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); } /**Function************************************************************* @@ -358,7 +230,6 @@ void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * 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; @@ -428,26 +299,6 @@ void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ) 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.] @@ -520,26 +371,10 @@ void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ) SeeAlso [] ***********************************************************************/ -void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ) +void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile ) { 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; - } + int i, Length; // print the delay profile if ( fProfile && Abc_NtkHasMapping(pNtk) ) @@ -581,7 +416,7 @@ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListN int nOutsSum, nOutsTotal; if ( !Abc_NtkIsStrash(pNtk) ) - Abc_NtkLevel(pNtk); + Abc_NtkGetLevelNum(pNtk); LevelMax = 0; Abc_NtkForEachCo( pNtk, pNode, i ) @@ -663,289 +498,6 @@ void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ) 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 618b6a0f..00000000 --- a/src/base/abci/abcProve.c +++ /dev/null @@ -1,341 +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( "Miter = %d (%3.1f). Rwr = %d (%3.1f). Fraig = %d (%3.1f). Last = %d.\n", - pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, - pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, - pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti, 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 index e77f055a..60a02aed 100644 --- a/src/base/abci/abcReconv.c +++ b/src/base/abci/abcReconv.c @@ -44,7 +44,7 @@ static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLe static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -321,9 +321,7 @@ int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int { 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) ) + if ( CostBest > CostCur ) { CostBest = CostCur; pFaninBest = pNode; @@ -491,20 +489,18 @@ void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ) SeeAlso [] ***********************************************************************/ -DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited ) +DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, 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 ); + Abc_NodeConeCollect( &pNode, 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 ); @@ -589,7 +585,7 @@ Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNode p->vConeLeaves = Vec_PtrAlloc( 100 ); p->vVisited = Vec_PtrAlloc( 100 ); p->vLevels = Vec_VecAlloc( 100 ); - p->vNodesTfo = Vec_PtrAlloc( 100 ); + p->vNodesTfo = Vec_PtrAlloc( 100 ); p->nNodeSizeMax = nNodeSizeMax; p->nConeSizeMax = nConeSizeMax; p->nNodeFanStop = nNodeFanStop; @@ -634,22 +630,6 @@ 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.] @@ -712,7 +692,7 @@ Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Pt // mark MFFC if ( pRoot ) - Abc_NodeMffcLabelAig( pRoot ); + Abc_NodeMffcLabel( pRoot ); // go through the levels up Vec_PtrClear( p->vNodesTfo ); diff --git a/src/base/abci/abcRefactor.c b/src/base/abci/abcRefactor.c index b925f1b9..92d497fc 100644 --- a/src/base/abci/abcRefactor.c +++ b/src/base/abci/abcRefactor.c @@ -43,8 +43,6 @@ struct Abc_ManRef_t_ int nNodesConsidered; int nNodesRefactored; int nNodesGained; - int nNodesBeg; - int nNodesEnd; // runtime statistics int timeCut; int timeBdd; @@ -60,10 +58,10 @@ struct Abc_ManRef_t_ 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 ); +static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUseZeros, bool fUseDcs, bool fVerbose ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -82,9 +80,8 @@ static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec SeeAlso [] ***********************************************************************/ -int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ) +int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseZeros, bool fUseDcs, bool fVerbose ) { - extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ); ProgressBar * pProgress; Abc_ManRef_t * pManRef; Abc_ManCut_t * pManCut; @@ -101,22 +98,16 @@ int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool 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 ); + Abc_NtkStartReverseLevels( pNtk ); // 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) ) + if ( Abc_NodeIsConst(pNode) ) continue; // skip the nodes with many fanouts if ( Abc_ObjFanoutNum(pNode) > 1000 ) @@ -130,23 +121,18 @@ clk = clock(); pManRef->timeCut += clock() - clk; // evaluate this cut clk = clock(); - pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); + pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, 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 ); + Dec_GraphUpdateNetwork( pNode, pFForm, 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 ) @@ -154,14 +140,7 @@ pManRef->timeTotal = clock() - clkStart; // 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 ); + Abc_NtkStopReverseLevels( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { @@ -182,18 +161,14 @@ pManRef->timeTotal = clock() - clkStart; 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 ) +Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUseZeros, bool fUseDcs, bool fVerbose ) { - extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); 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++; @@ -239,7 +214,7 @@ p->timeDcs += clock() - clk; // get the SOP of the cut clk = clock(); - pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, 0, p->vCube, -1 ); + pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, p->vCube, -1 ); p->timeSop += clock() - clk; // get the factored form @@ -254,7 +229,7 @@ p->timeFact += clock() - clk; pFanin->vFanouts.nSize++; // label MFFC with current traversal ID Abc_NtkIncrementTravId( pNode->pNtk ); - nNodesSaved = Abc_NodeMffcLabelAig( pNode ); + nNodesSaved = Abc_NodeMffcLabel( pNode ); // unmark the fanin boundary and set the fanins as leaves in the form Vec_PtrForEachEntry( vFanins, pFanin, i ) { @@ -264,7 +239,7 @@ p->timeFact += clock() - clk; // detect how many new nodes will be added (while taking into account reused nodes) clk = clock(); - nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required ); + nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Abc_NodeReadRequiredLevel(pNode) ); p->timeEval += clock() - clk; // quit if there is no improvement if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !fUseZeros ) @@ -361,7 +336,7 @@ 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 ); + printf( "Calculated gain = %8d.\n", p->nNodesGained ); PRT( "Cuts ", p->timeCut ); PRT( "Resynthesis", p->timeRes ); PRT( " BDD ", p->timeBdd ); diff --git a/src/base/abci/abcRenode.c b/src/base/abci/abcRenode.c index 8e8e8719..165777f8 100644 --- a/src/base/abci/abcRenode.c +++ b/src/base/abci/abcRenode.c @@ -6,7 +6,7 @@ PackageName [Network and node package.] - Synopsis [] + Synopsis [Procedures which transform an AIG into the network of SOP logic nodes.] Author [Alan Mishchenko] @@ -19,135 +19,181 @@ ***********************************************************************/ #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 void Abc_NtkRenodeInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NtkRenode_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ); -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 DdNode * Abc_NtkRenodeDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins ); -static int nDsdCounter = 0; +static void Abc_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ); +static void Abc_NtkRenodeSetBoundsCnf( Abc_Ntk_t * pNtk ); +static void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ); +static void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk ); +static void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Performs renoding as technology mapping.] + Synopsis [Transforms the AIG into nodes.] - Description [] + Description [Threhold is the max number of nodes duplicated at a node.] 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 ) +Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple ) { - extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); - If_Par_t Pars, * pPars = &Pars; 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( "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; + printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" ); + + // define the boundary + if ( fCnf ) + Abc_NtkRenodeSetBoundsCnf( pNtk ); + else if ( fMulti ) + Abc_NtkRenodeSetBoundsMulti( pNtk, nThresh ); + else if ( fSimple ) + Abc_NtkRenodeSetBoundsSimple( pNtk ); else - pPars->pFuncCost = Abc_NtkRenodeEvalAig; + Abc_NtkRenodeSetBounds( pNtk, nThresh, nFaninMax ); + + // perform renoding for this boundary + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD ); + Abc_NtkRenodeInt( pNtk, pNtkNew ); + Abc_NtkFinalize( pNtk, pNtkNew ); - // start the manager - if ( fUseBdds ) + // 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 ) { - 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; +// 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 ); } - else +//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) ); + + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) { - assert( s_vMemory == NULL ); - s_vMemory = Vec_IntAlloc( 1 << 16 ); - s_vMemory2 = Vec_IntAlloc( 1 << 16 ); + printf( "Abc_NtkRenode: 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 [] - // perform mapping/renoding - pNtkNew = Abc_NtkIf( pNtk, pPars ); +***********************************************************************/ +void Abc_NtkRenodeInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pConst1, * pNodeNew; + int i; - // start the manager - if ( fUseBdds ) + // set the constant node + pConst1 = Abc_AigConst1(pNtk->pManFunc); + if ( Abc_ObjFanoutNum(pConst1) > 0 ) { - Extra_StopManager( s_pDd ); - Extra_ReorderQuit( s_pReo ); - s_pReo = NULL; - s_pDd = NULL; + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData ); + pConst1->pCopy = pNodeNew; } - else + + // perform renoding for POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) { - Vec_IntFree( s_vMemory ); - Vec_IntFree( s_vMemory2 ); - s_vMemory = NULL; - s_vMemory2 = NULL; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) + continue; + Abc_NtkRenode_rec( pNtkNew, Abc_ObjFanin0(pNode) ); } + Extra_ProgressBarStop( pProgress ); -// printf( "Decomposed %d functions.\n", nDsdCounter ); + // clean the boundaries and data field in the old network + Abc_NtkForEachObj( pNtk, pNode, i ) + { + pNode->fMarkA = 0; + pNode->pData = NULL; + } +} - return pNtkNew; +/**Function************************************************************* + + Synopsis [Find the best multi-input node rooted at the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkRenode_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_NodeIsConst(pNodeOld) ); + assert( pNodeOld->fMarkA ); + + // collect the renoding cone + vCone = Vec_PtrAlloc( 10 ); + Abc_NtkRenodeCone( pNodeOld, vCone ); + + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < vCone->nSize; i++ ) + Abc_ObjAddFanin( pNodeNew, Abc_NtkRenode_rec(pNtkNew, vCone->pArray[i]) ); + + // derive the function of this node + pNodeNew->pData = Abc_NtkRenodeDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone ); + Cudd_Ref( pNodeNew->pData ); + Vec_PtrFree( vCone ); + + // remember the node + pNodeOld->pCopy = pNodeNew; + return pNodeOld->pCopy; } + /**Function************************************************************* - Synopsis [Computes the cost based on the factored form.] + Synopsis [Derives the local BDD of the node.] Description [] @@ -156,35 +202,296 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF SeeAlso [] ***********************************************************************/ -int Abc_NtkRenodeEvalAig( If_Cut_t * pCut ) +DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ) { - Kit_Graph_t * pGraph; - int i, nNodes; -/* -extern void Kit_DsdTest( unsigned * pTruth, int nVars ); -if ( If_CutLeaveNum(pCut) == 8 ) + Abc_Obj_t * pFaninOld; + DdNode * bFunc; + int i; + assert( !Abc_NodeIsConst(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_NtkRenodeDeriveBdd_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_NtkRenodeDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins ) { - nDsdCounter++; - Kit_DsdTest( If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + 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_NtkRenodeDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 ); + bFunc1 = Abc_NtkRenodeDeriveBdd_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; } -*/ - pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory ); - if ( pGraph == NULL ) + + + +/**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_NtkRenodeLimit_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_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 ); + Abc_NtkRenodeLimit_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_NtkRenodeLimit_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_NtkRenodeLimit_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_NtkRenodeLimit_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_NtkRenodeLimit_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_NtkRenodeLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax ) +{ + vCone->nSize = 0; + return Abc_NtkRenodeLimit_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_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ) +{ + Vec_Ptr_t * vCone = pNtk->vPtrTemp; + 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 ntil it meets the fanin limit + while ( Abc_NtkRenodeLimit(pNode, vCone, nFaninMax) ); + assert( vCone->nSize <= nFaninMax ); + } +/* + // make sure the fanin limit is met + Abc_NtkForEachNode( pNtk, pNode, i ) { - for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) - pCut->pPerm[i] = 100; - return IF_COST_MAX; + // skip PI/PO nodes + if ( Abc_NodeIsConst(pNode) ) + continue; + if ( pNode->fMarkA == 0 ) + continue; + Abc_NtkRenodeCone( pNode, vCone ); + assert( vCone->nSize <= nFaninMax ); } - 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.] + 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_NtkRenodeSetBoundsCnf( 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 [] @@ -193,27 +500,44 @@ if ( If_CutLeaveNum(pCut) == 8 ) SeeAlso [] ***********************************************************************/ -int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut ) +void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ) { - 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; + 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 [Computes the cost based on ISOP.] + Synopsis [Sets a simple boundary.] Description [] @@ -222,21 +546,21 @@ int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut ) SeeAlso [] ***********************************************************************/ -int Abc_NtkRenodeEvalSop( If_Cut_t * pCut ) +void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk ) { - 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 ); + 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 [Computes the cost based on two ISOPs.] + Synopsis [Collects the fanins of a large node.] Description [] @@ -245,32 +569,21 @@ int Abc_NtkRenodeEvalSop( If_Cut_t * pCut ) SeeAlso [] ***********************************************************************/ -int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut ) +void Abc_NtkRenodeCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) { - 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; + assert( !Abc_ObjIsComplement(pNode) ); + if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) ) + { + Vec_PtrPushUnique( vCone, pNode ); + return; + } + Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,0), vCone ); + Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,1), vCone ); } /**Function************************************************************* - Synopsis [Computes the cost of MV-SOP of the cut function.] + Synopsis [Collects the fanins of a large node.] Description [] @@ -279,29 +592,13 @@ int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut ) SeeAlso [] ***********************************************************************/ -int Abc_NtkRenodeEvalMv( If_Cut_t * pCut ) +void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) { - 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; + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + vCone->nSize = 0; + Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,0), vCone ); + Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,1), vCone ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcReorder.c b/src/base/abci/abcReorder.c deleted file mode 100644 index 182780cd..00000000 --- a/src/base/abci/abcReorder.c +++ /dev/null @@ -1,102 +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; - Abc_NtkRemoveDupFanins( pNtk ); - Abc_NtkMinimumBase( pNtk ); - 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 aa9a2998..00000000 --- a/src/base/abci/abcRestruct.c +++ /dev/null @@ -1,1497 +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 ) -{ - extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ); - 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 a2b23c0c..00000000 --- a/src/base/abci/abcResub.c +++ /dev/null @@ -1,1952 +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 ) -{ - extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ); - 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 index 3b50107b..ea221296 100644 --- a/src/base/abci/abcRewrite.c +++ b/src/base/abci/abcRewrite.c @@ -32,16 +32,11 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ); +static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop ); 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -55,54 +50,31 @@ extern void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets SeeAlso [] ***********************************************************************/ -int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ) +int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUseZeros, int fVerbose ) { - extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ); + int fDrop = 0; 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 i, nNodes, nGain; 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 ); + Abc_NtkStartReverseLevels( pNtk ); // start the cut manager clk = clock(); - pManCut = Abc_NtkStartCutManForRewrite( pNtk ); + pManCut = Abc_NtkStartCutManForRewrite( pNtk, fDrop ); 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 ) @@ -111,71 +83,34 @@ Rwr_ManAddTimeCuts( pManRwr, clock() - clk ); // stop if all nodes have been tried once if ( i >= nNodes ) break; - // skip persistant nodes - if ( Abc_NodeIsPersistant(pNode) ) + // skip the constant node + if ( Abc_NodeIsConst(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 ); + nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUseZeros ); + if ( nGain > 0 || nGain == 0 && fUseZeros ) + { + Dec_Graph_t * pGraph = Rwr_ManReadDecs(pManRwr); + int fCompl = Rwr_ManReadCompl(pManRwr); + // complement the FF if needed + if ( fCompl ) Dec_GraphComplement( pGraph ); + Dec_GraphUpdateNetwork( pNode, pGraph, nGain ); + if ( fCompl ) Dec_GraphComplement( pGraph ); + } } 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 ); + Abc_NtkStopReverseLevels( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { @@ -197,7 +132,7 @@ Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart ); SeeAlso [] ***********************************************************************/ -Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ) +Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop ) { static Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pManCut; @@ -208,9 +143,10 @@ Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ) 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->fHash = 1; // hash cuts to detect unique + pParams->fFilter = 0; // filter dominated cuts pParams->fSeq = 0; // compute sequential cuts - pParams->fDrop = 0; // drop cuts on the fly + pParams->fDrop = fDrop; // drop cuts on the fly pParams->fVerbose = 0; // the verbosiness flag pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); pManCut = Cut_ManStart( pParams ); @@ -236,178 +172,19 @@ Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ) ***********************************************************************/ void Abc_NodePrintCuts( Abc_Obj_t * pNode ) { - Vec_Ptr_t * vCuts; Cut_Cut_t * pCut; - int k; - + unsigned uTruth; printf( "\nNode %s\n", Abc_ObjName(pNode) ); - vCuts = (Vec_Ptr_t *)pNode->pCopy; - Vec_PtrForEachEntry( vCuts, pCut, k ) + for ( pCut = (Cut_Cut_t *)pNode->pCopy; pCut; pCut = pCut->pNext ) { - Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 ); + uTruth = pCut->uTruth; + Extra_PrintBinary( stdout, &uTruth, 16 ); printf( " " ); - Cut_CutPrint( pCut, 0 ); + Cut_CutPrint( pCut ); 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 index 58614584..4fb059e5 100644 --- a/src/base/abci/abcSat.c +++ b/src/base/abci/abcSat.c @@ -6,7 +6,7 @@ PackageName [Network and node package.] - Synopsis [Procedures to solve the miter using the internal SAT sat_solver.] + Synopsis [Procedures to solve the miter using the internal SAT solver.] Author [Alan Mishchenko] @@ -19,167 +19,79 @@ ***********************************************************************/ #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; +static void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars ); +static void Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Attempts to solve the miter using an internal SAT sat_solver.] + Synopsis [Attempts to solve the miter using an internal SAT solver.] - Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] + Description [Returns 1 if the miter is SAT.] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects ) +bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose ) { - sat_solver * pSat; + solver * pSat; lbool status; - int RetValue, clk; - - if ( pNumConfs ) - *pNumConfs = 0; - if ( pNumInspects ) - *pNumInspects = 0; + int clk; + assert( Abc_NtkIsBddLogic(pNtk) ); 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) ); + if ( Abc_NtkPoNum(pNtk) > 1 ) + fprintf( stdout, "Warning: The miter has more than 1 output. SAT will try to prove all of them.\n" ); - // load clauses into the sat_solver + // load clauses into the 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) ); + pSat = Abc_NtkMiterSatCreate( pNtk ); +// printf( "Created SAT problem with %d variable and %d clauses. ", +// solver_nvars(pSat), 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) ); + status = solver_simplify(pSat); +// printf( "Simplified the problem to %d variables and %d clauses. ", +// solver_nvars(pSat), solver_nclauses(pSat) ); // PRT( "Time", clock() - clk ); - if ( status == 0 ) + if ( status == l_False ) { - sat_solver_delete( pSat ); -// printf( "The problem is UNSATISFIABLE after simplification.\n" ); - return 1; + solver_delete( pSat ); + printf( "The problem is UNSAT after simplification.\n" ); + return 0; } // 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; + status = solver_solve( pSat, NULL, NULL ); +// if ( fVerbose ) +// { + printf( "The problem is %5s. ", (status == l_True)? "SAT" : "UNSAT" ); + PRT( "SAT solver time", clock() - clk ); +// } + // free the solver + solver_delete( pSat ); + return status == l_True; } /**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.] + Synopsis [Sets up the SAT solver.] Description [] @@ -188,461 +100,43 @@ int Abc_NtkClauseTriv( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) SeeAlso [] ***********************************************************************/ -int Abc_NtkClauseTop( sat_solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars ) +solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk ) { + solver * pSat; + Extra_MmFlex_t * pMmFlex; 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_Str_t * vCube; 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) ); + char * pSop0, * pSop1; + int i; - // clean the CI node pointers - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pCopy = NULL; + assert( Abc_NtkIsBddLogic(pNtk) ); // 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 ); + pSat = solver_new(); + pMmFlex = Extra_MmFlexStart(); + vCube = Vec_StrAlloc( 100 ); + vVars = Vec_IntAlloc( 100 ); - // 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 ) + // add clauses for each internal nodes + Abc_NtkForEachNode( pNtk, pNode, i ) { - 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 ); + // derive SOPs for both phases of the node + Abc_NodeBddToCnf( pNode, pMmFlex, vCube, &pSop0, &pSop1 ); + // add the clauses to the solver + Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ); } -*/ - RetValue = 1; -Quits : + // add clauses for each PO + Abc_NtkForEachPo( pNtk, pNode, i ) + Abc_NodeAddClausesTop( pSat, pNode, vVars ); + // delete + Vec_StrFree( vCube ); 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 ); + Extra_MmFlexStop( pMmFlex, 0 ); return pSat; } - - - /**Function************************************************************* Synopsis [Adds clauses for the internal node.] @@ -654,33 +148,14 @@ sat_solver_store_mark_roots( pSat ); SeeAlso [] ***********************************************************************/ -int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars ) +void Abc_NodeAddClauses( 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++ ) @@ -696,15 +171,10 @@ int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t 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; + Vec_IntPush( vVars, neg(toLit(pFanin->Id)) ); } + Vec_IntPush( vVars, neg(toLit(pNode->Id)) ); + solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } // add clauses for the positive phase @@ -721,17 +191,11 @@ int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t 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, 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; - } + solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } - return 1; } /**Function************************************************************* @@ -745,10 +209,9 @@ int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t SeeAlso [] ***********************************************************************/ -int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) +void Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) { Abc_Obj_t * pFanin; - int RetValue; pFanin = Abc_ObjFanin0(pNode); if ( Abc_ObjFaninC0(pNode) ) @@ -756,126 +219,31 @@ int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVa 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; - } + solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); 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; - } + Vec_IntPush( vVars, neg(toLit(pFanin->Id)) ); + Vec_IntPush( vVars, neg(toLit(pNode->Id)) ); + solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } else { vVars->nSize = 0; - Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + Vec_IntPush( vVars, 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; - } + solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); 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; - } + Vec_IntPush( vVars, neg(toLit(pNode->Id)) ); + solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } 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; + solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } -/**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 index c77f8dea..de87a1e9 100644 --- a/src/base/abci/abcStrash.c +++ b/src/base/abci/abcStrash.c @@ -1,6 +1,6 @@ /**CFile**************************************************************** - FileName [abcStrash.c] + FileName [aigStrash.c] SystemName [ABC: Logic synthesis and verification system.] @@ -14,7 +14,7 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + Revision [$Id: aigStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ @@ -26,170 +26,52 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ); +// static functions +static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fAllNodes ); +static Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop ); +static Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop ); + +extern char * Mio_GateReadSop( void * pGate ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Reapplies structural hashing to the AIG.] + Synopsis [Creates the strashed AIG network.] - 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.] + Description [Converts the logic network or the AIG into a + structurally hashed AIG.] SideEffects [] SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ) +Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, 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 [] + int nNodes; -***********************************************************************/ -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(); + assert( !Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkIsBddLogic(pNtk) ) + Abc_NtkBddToSop(pNtk); // 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; - } + printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); // perform strashing -// Abc_NtkCleanCopy( pNtk ); - pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord ); + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG ); + Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes ); 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 ); + if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) + printf( "The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); + if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Cleanup has removed %d nodes.\n", nNodes ); // duplicate EXDC if ( pNtk->pExdc ) - pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + pNtkAig->pExdc = Abc_NtkStrash( pNtk->pExdc, 0, 1 ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkAig ) ) { @@ -205,85 +87,34 @@ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fR 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.] + Performs structural hashing while appending the networks. Does not add + the COs of the second. 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 ) +int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) { Abc_Obj_t * pObj; - char * pName; - int i, nNewCis; + int i; // 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; - } + if ( Abc_NtkIsBddLogic(pNtk2) ) + Abc_NtkBddToSop(pNtk2); // 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" ); + if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1 ) ) + return 0; // 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 ); + pObj->pCopy = Abc_NtkCi(pNtk1, i); // 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) ); - } - } + Abc_NtkStrashPerform( pNtk2, pNtk1, 1 ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtk1 ) ) { @@ -293,6 +124,7 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ) return 1; } + /**Function************************************************************* Synopsis [Prepares the network for strashing.] @@ -304,31 +136,38 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ) SeeAlso [] ***********************************************************************/ -void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ) +void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, bool fAllNodes ) { ProgressBar * pProgress; + Abc_Aig_t * pMan = pNtkNew->pManFunc; 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 ); + Abc_Obj_t * pNode, * pNodeNew, * pObj; + int i; + + // perform strashing + vNodes = Abc_NtkDfs( pNtk, fAllNodes ); pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); - Vec_PtrForEachEntry( vNodes, pNodeOld, i ) + Vec_PtrForEachEntry( vNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord ); + // get the node + assert( Abc_ObjIsNode(pNode) ); + // strash the node + pNodeNew = Abc_NodeStrash( pMan, pNode ); + // get the old object + pObj = Abc_ObjFanout0Ntk( pNode ); + // make sure the node is not yet strashed + assert( pObj->pCopy == NULL ); + // mark the old object with the new AIG node + pObj->pCopy = pNodeNew; } - Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); + Extra_ProgressBarStop( pProgress ); } /**Function************************************************************* - Synopsis [Transfers the AIG from one manager into another.] + Synopsis [Strashes one logic node.] Description [] @@ -337,76 +176,40 @@ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNod SeeAlso [] ***********************************************************************/ -void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj ) +Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) { - 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************************************************************* + int fUseFactor = 1; + char * pSop; - Synopsis [Strashes one logic node.] + assert( Abc_ObjIsNode(pNode) ); - 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() ) + // consider the case when the graph is an AIG + if ( Abc_NtkIsStrash(pNode->pNtk) ) { - 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; + if ( Abc_NodeIsConst(pNode) ) + return Abc_AigConst1(pMan); + return Abc_AigAnd( pMan, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } - // 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) ); -} - - - + // 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 Abc_ObjNotCond( Abc_AigConst1(pMan), Abc_SopIsConst0(pSop) ); + // decide when to use factoring + if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 ) + return Abc_NodeStrashFactor( pMan, pNode, pSop ); + return Abc_NodeStrashSop( pMan, pNode, pSop ); +} /**Function************************************************************* - Synopsis [Copies the topmost levels of the network.] + Synopsis [Strashes one logic node using its SOP.] Description [] @@ -415,21 +218,41 @@ Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fReco SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut ) +Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop ) { - 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) ); + Abc_Obj_t * pFanin, * pAnd, * pSum; + Abc_Obj_t * pConst1 = Abc_AigConst1(pMan); + 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 = Abc_ObjNot(pConst1); + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + pAnd = pConst1; + Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net + { + if ( pCube[i] == '1' ) + pAnd = Abc_AigAnd( pMan, pAnd, pFanin->pCopy ); + else if ( pCube[i] == '0' ) + pAnd = Abc_AigAnd( pMan, pAnd, Abc_ObjNot(pFanin->pCopy) ); + } + // add to the sum of cubes + pSum = Abc_AigOr( pMan, pSum, pAnd ); + } + // decide whether to complement the result + if ( Abc_SopIsComplement(pSop) ) + pSum = Abc_ObjNot(pSum); + return pSum; } /**Function************************************************************* - Synopsis [Copies the topmost levels of the network.] + Synopsis [Strashes one logic node using its SOP.] Description [] @@ -438,39 +261,23 @@ Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int Leve SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) +Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, char * pSop ) { - 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; + Dec_Graph_t * pFForm; + Dec_Node_t * pNode; + Abc_Obj_t * pAnd; + int i; + // 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_GraphToNetwork( pMan, pFForm ); + Dec_GraphFree( pFForm ); + return pAnd; } - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcSweep.c b/src/base/abci/abcSweep.c index 1ae8745b..7000ecad 100644 --- a/src/base/abci/abcSweep.c +++ b/src/base/abci/abcSweep.c @@ -25,20 +25,20 @@ /// 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 ); +extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes ); + +static stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv, bool fVerbose ); 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 void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fVerbose, int fUseInv ); +static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fVerbose, int fUseInv ); 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -54,57 +54,22 @@ static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pF SeeAlso [] ***********************************************************************/ -bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ) +bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose ) { 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; - } - + pNtkAig = Abc_NtkStrash( pNtk, 0, 1 ); // 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 ); - + pMan = Abc_NtkToFraig( pNtkAig, &Params, 0 ); // collect the classes of equivalent nets - tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose ); + tEquiv = Abc_NtkFraigEquiv( pMan, pNtk, fUseInv, fVerbose ); // transform the network into the equivalent one Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose ); @@ -115,11 +80,7 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, Abc_NtkDelete( pNtkAig ); // cleanup the dangling nodes - if ( Abc_NtkHasMapping(pNtk) ) - Abc_NtkCleanup( pNtk, fVerbose ); - else - Abc_NtkSweep( pNtk, fVerbose ); - + Abc_NtkCleanup( pNtk, fVerbose ); // check if ( !Abc_NtkCheck( pNtk ) ) { @@ -129,47 +90,6 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, 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.] @@ -181,7 +101,7 @@ void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ) +stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv, bool fVerbose ) { Abc_Obj_t * pList, * pNode, * pNodeAig; Fraig_Node_t * gNode; @@ -195,16 +115,16 @@ stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int 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) ) + // skip the constant input nodes + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + // skip the nodes that fanout into POs + if ( Abc_NodeHasUniqueCoFanout(pNode) ) continue; // get the FRAIG node gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) ); @@ -231,22 +151,22 @@ stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int // count nodes in the non-trival classes for ( pNode = pList; pNode; pNode = pNode->pNext ) Counter++; - - if ( fVeryVerbose ) +/* + if ( fVerbose ) { 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 ); + if ( pNode->fPhase ) printf( "(*)" ); } printf( " }\n" ); c++; } +*/ } - if ( fVerbose || fVeryVerbose ) + if ( fVerbose ) { 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) ); @@ -274,6 +194,8 @@ void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, Abc_Obj_t * pList; if ( stmm_count(tEquiv) == 0 ) return; + // assign levels to the nodes of the network + Abc_NtkGetLevelNum( pNtk ); // merge nodes in the classes if ( Abc_NtkHasMapping( pNtk ) ) { @@ -335,8 +257,8 @@ void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUs { Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst; Arrival2 = Abc_NodeReadArrival(pNode )->Worst; -// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); -// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); + 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 && @@ -355,8 +277,8 @@ void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUs { Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst; Arrival2 = Abc_NodeReadArrival(pNode )->Worst; -// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); -// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); + 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 && @@ -430,7 +352,7 @@ void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, return; // add the invertor - pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin ); + pNodeMinInv = Abc_NodeCreateInv( pNtk, pNodeMin ); // move the fanouts of the inverted nodes for ( pNode = pListInv; pNode; pNode = pNode->pNext ) @@ -472,36 +394,19 @@ int Abc_NodeDroppingCost( Abc_Obj_t * pNode ) 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 ) + vNodes = Abc_NtkDfs( pNtk, 0 ); + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNode = vNodes->pArray[i]; pNode->fMarkA = 1; + } + Vec_PtrFree( vNodes ); + // if it is an AIG, also mark the constant 1 node + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk->pManFunc)->fMarkA = 1; // remove the non-marked nodes Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) @@ -511,11 +416,16 @@ int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) Counter++; } // unmark the remaining nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) + Abc_NtkForEachNode( pNtk, pNode, i ) pNode->fMarkA = 0; + if ( fVerbose ) + printf( "Cleanup removed %d dangling nodes.\n", Counter ); // check if ( !Abc_NtkCheck( pNtk ) ) + { printf( "Abc_NtkCleanup: The network check has failed.\n" ); + return -1; + } return Counter; } @@ -535,40 +445,85 @@ int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) ***********************************************************************/ 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_Obj_t * pNode; + int i, fConvert, nSwept, nSweptNew; + assert( Abc_NtkIsSopLogic(pNtk) || Abc_NtkIsBddLogic(pNtk) ); + // convert to the BDD representation + fConvert = 0; + if ( Abc_NtkIsSopLogic(pNtk) ) + Abc_NtkSopToBdd(pNtk), fConvert = 1; + // perform cleanup to get rid of dangling nodes + nSwept = Abc_NtkCleanup( pNtk, 0 ); + // make the network minimum base 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 ) + do { - // 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 ) + // sweep constants and single-input nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_ObjFaninNum(pNode) < 2 ) + Abc_NodeSweep( pNode, fVerbose ); + // make the network minimum base + Abc_NtkRemoveDupFanins(pNtk); + Abc_NtkMinimumBase(pNtk); + // perform final clean up (in case new danglies are created) + nSweptNew = Abc_NtkCleanup( pNtk, 0 ); + nSwept += nSweptNew; + } + while ( nSweptNew ); + // conver back to BDD + if ( fConvert ) + Abc_NtkBddToSop(pNtk); + // report + if ( fVerbose ) + printf( "Sweep removed %d nodes.\n", nSwept ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkSweep: The network check has failed.\n" ); + return -1; + } + return nSwept; +} + +/**Function************************************************************* + + Synopsis [Tranditional sweep of the network.] + + Description [Propagates constant and single-input node, removes dangling nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose ) +{ + Vec_Ptr_t * vFanout = pNode->pNtk->vPtrTemp; + Abc_Obj_t * pFanout, * pDriver; + int i; + assert( Abc_ObjFaninNum(pNode) < 2 ); + assert( Abc_ObjFanoutNum(pNode) > 0 ); + // iterate through the fanouts + Abc_NodeCollectFanouts( pNode, vFanout ); + Vec_PtrForEachEntry( vFanout, pFanout, i ) + { + if ( Abc_ObjIsCo(pFanout) ) + { + if ( Abc_ObjFaninNum(pNode) == 1 ) + { + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 1 || Abc_ObjFanoutNum(pNode) > 1 ) + continue; + // the driver is a node and its only fanout is this node + if ( Abc_NodeIsInv(pNode) ) + pDriver->pData = Cudd_Not(pDriver->pData); + // replace the fanin of the fanout + Abc_ObjPatchFanin( pFanout, pNode, pDriver ); + } continue; - assert( Abc_ObjIsNode(pFanout) ); - // transform the function of the fanout + } + // the fanout is a regular node if ( Abc_ObjFaninNum(pNode) == 0 ) Abc_NodeConstantInput( pFanout, pNode, Abc_NodeIsConst0(pNode) ); else @@ -579,44 +534,9 @@ int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ) 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.] @@ -634,7 +554,7 @@ void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 DdNode * bVar, * bTemp; int iFanin; assert( Abc_NtkIsBddLogic(pNode->pNtk) ); - if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) + if ( (iFanin = Vec_FanFindEntry( &pNode->vFanins, pFanin->Id )) == -1 ) { printf( "Node %s should be among", Abc_ObjName(pFanin) ); printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); @@ -662,7 +582,7 @@ void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) DdNode * bVar, * bCof0, * bCof1; int iFanin; assert( Abc_NtkIsBddLogic(pNode->pNtk) ); - if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) + if ( (iFanin = Vec_FanFindEntry( &pNode->vFanins, pFanin->Id )) == -1 ) { printf( "Node %s should be among", Abc_ObjName(pFanin) ); printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); @@ -677,270 +597,6 @@ void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) 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 index 0f76065c..f1e427c0 100644 --- a/src/base/abci/abcSymm.c +++ b/src/base/abci/abcSymm.c @@ -24,13 +24,13 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ); +static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -44,10 +44,10 @@ static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ) SeeAlso [] ***********************************************************************/ -void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ) +void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fVerbose ) { - if ( fUseBdds || fNaive ) - Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose ); + if ( fUseBdds ) + Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fVerbose ); else Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose ); } @@ -81,19 +81,15 @@ void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ) SeeAlso [] ***********************************************************************/ -void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ) +void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, 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) ); + dd = Abc_NtkGlobalBdds( pNtk, 0 ); Cudd_AutodynDisable( dd ); - if ( !fGarbCollect ) - Cudd_DisableGarbageCollection( dd ); Cudd_zddVarsFromBddVars( dd, 2 ); clkBdd = clock() - clk; // create the collapsed network @@ -101,10 +97,10 @@ 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" ); + Abc_NtkFreeGlobalBdds( pNtk ); + Extra_StopManager( dd ); + pNtk->pManGlob = NULL; + PRT( "Constructing BDDs", clkBdd ); PRT( "Computing symms ", clkSym ); PRT( "TOTAL ", clkBdd + clkSym ); @@ -133,8 +129,7 @@ void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVer // compute symmetry info for each PO Abc_NtkForEachCo( pNtk, pNode, i ) { -// bFunc = pNtk->vFuncsGlob->pArray[i]; - bFunc = Abc_ObjGlobalBdd( pNode ); + bFunc = pNtk->vFuncsGlob->pArray[i]; nSupps += Cudd_SupportSize( dd, bFunc ); if ( Cudd_IsConstant(bFunc) ) continue; diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c index 967e4617..b8524bd5 100644 --- a/src/base/abci/abcTiming.c +++ b/src/base/abci/abcTiming.c @@ -37,16 +37,16 @@ struct Abc_ManTime_t_ // 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 ); +static void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ); -void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ); +static 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -254,9 +254,9 @@ void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk ) continue; *pTime = pNtk->pManTime->tReqDef; } - // set the 0 arrival times for latch outputs and constant nodes + // set the 0 arrival times for latches and constant nodes ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; - Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + Abc_NtkForEachLatch( pNtk, pObj, i ) { pTime = ppTimes[pObj->Id]; pTime->Fall = pTime->Rise = pTime->Worst = 0.0; @@ -470,9 +470,9 @@ void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld ) int i; if ( pNtkOld->pManTime == NULL ) return; - if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen()) == NULL ) + if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) == NULL ) return; - tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen()); + tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())); Abc_NtkForEachPi( pNtkOld, pNodeOld, i ) { pNodeNew = pNodeOld->pCopy; @@ -595,12 +595,13 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ) // start the arrival time of the node pTimeOut = Abc_NodeArrival(pNode); - pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY; + pTimeOut->Rise = pTimeOut->Fall = 0; // go through the pins of the gate pPin = Mio_GateReadPins(pNode->pData); Abc_ObjForEachFanin( pNode, pFanin, i ) { pTimeIn = Abc_NodeArrival(pFanin); + assert( pTimeIn->Worst != -ABC_INFINITY ); // get the interesting parameters of this pin PinPhase = Mio_PinReadPhase(pPin); tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); @@ -630,133 +631,38 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ) /**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.] + Synopsis [Prepares the AIG for the comptuation 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.] + from the COs of the AIG nodes in reverse topologogical order.] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ) +void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i; + Abc_Obj_t * pObj, * pFanout; + int i, k, nLevelsCur; + assert( Abc_NtkIsStrash(pNtk) ); // remember the maximum number of direct levels - pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease; + pNtk->LevelMax = Abc_AigGetLevelNum(pNtk); // start the reverse levels pNtk->vLevelsR = Vec_IntAlloc( 0 ); - Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 ); + Vec_IntFill( pNtk->vLevelsR, 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) ); + { + nLevelsCur = 0; + Abc_ObjForEachFanout( pObj, pFanout, k ) + if ( nLevelsCur < Vec_IntEntry(pNtk->vLevelsR, pFanout->Id) ) + nLevelsCur = Vec_IntEntry(pNtk->vLevelsR, pFanout->Id); + Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, nLevelsCur + 1 ); + } Vec_PtrFree( vNodes ); } @@ -782,120 +688,64 @@ void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ) /**Function************************************************************* - Synopsis [Incrementally updates level of the nodes.] + Synopsis [Sets the reverse level of the node.] - Description [] + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +void Abc_NodeSetReverseLevel( Abc_Obj_t * pObj, int LevelR ) { - 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; - } - } - } + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( Abc_NtkIsStrash(pNtk) ); + assert( pNtk->vLevelsR ); + Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); + Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR ); } /**Function************************************************************* - Synopsis [Incrementally updates level of the nodes.] + Synopsis [Returns the reverse level of the node.] - Description [] + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +int Abc_NodeReadReverseLevel( Abc_Obj_t * pObj ) { - 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; - } - } - } + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( Abc_NtkIsStrash(pNtk) ); + assert( pNtk->vLevelsR ); + Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); + return Vec_IntEntry(pNtk->vLevelsR, pObj->Id); } /**Function************************************************************* - Synopsis [Replaces the node and incrementally updates levels.] + Synopsis [Returns required level of the node.] - Description [] + Description [Converts the reverse levels of the node into its required + level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] SideEffects [] SeeAlso [] ***********************************************************************/ -void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +int Abc_NodeReadRequiredLevel( Abc_Obj_t * pObj ) { - // 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 ); + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( Abc_NtkIsStrash(pNtk) ); + assert( pNtk->vLevelsR ); + return pNtk->LevelMax + 1 - Vec_IntEntry(pNtk->vLevelsR, pObj->Id); } //////////////////////////////////////////////////////////////////////// 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 index ea0a4cd2..abc02cc3 100644 --- a/src/base/abci/abcUnreach.c +++ b/src/base/abci/abcUnreach.c @@ -30,7 +30,7 @@ static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -58,11 +58,11 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) } // compute the global BDDs of the latches - dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + dd = Abc_NtkGlobalBdds( pNtk, 1 ); if ( dd == NULL ) return 0; if ( fVerbose ) - printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); // create the transition relation (dereferenced global BDDs) bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose ); Cudd_Ref( bRelation ); @@ -87,15 +87,13 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) // 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; + pNtk->pManGlob = NULL; // make sure that everything is okay - if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) ) + if ( !Abc_NtkCheck( pNtk->pExdc ) ) { printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" ); Abc_NtkDelete( pNtk->pExdc ); @@ -137,15 +135,13 @@ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbo 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 ); + bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); 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 ); + Abc_NtkFreeGlobalBdds( pNtk ); // quantify the PI variables bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs ); @@ -221,7 +217,7 @@ DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * b { DdNode * bRelation, * bReached, * bCubeCs; DdNode * bCurrent, * bNext, * bTemp; - int nIters, nMints; + int nIters; // perform reachability analisys bCurrent = bInitial; Cudd_Ref( bCurrent ); @@ -258,9 +254,9 @@ DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * b // 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; - + pNtkNew = Abc_NtkAlloc( ABC_TYPE_LOGIC, ABC_FUNC_BDD ); // 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 + Abc_NtkForEachLatch( pNtk, pNode, i ) + pNode->pCopy = Abc_NtkCreatePi(pNtkNew); // create a new node pNodeNew = Abc_NtkCreateNode(pNtkNew); // add the fanins corresponding to latch outputs - Abc_NtkForEachLatchOutput( pNtk, pNode, i ) + Abc_NtkForEachLatch( pNtk, pNode, i ) Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); // create the logic function @@ -312,34 +304,28 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn 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 ); + // make the new node drive all the COs + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew ); - // link to the POs of the network + // store the PI names of the EXDC network + Abc_NtkForEachLatch( pNtk, pNode, i ) + Abc_NtkLogicStoreName( Abc_NtkPi(pNtkNew,i), Abc_ObjName(pNode) ); + // store the PO names of the EXDC 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 ); + Abc_NtkLogicStoreName( Abc_NtkPo(pNtkNew,i), Abc_ObjName(pNode) ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + Abc_NtkLogicStoreName( Abc_NtkCo(pNtkNew,Abc_NtkPoNum(pNtk) + i), Abc_ObjNameSuffix(pNode, "_in") ); - // remove the extra nodes - Abc_AigCleanup( pNtkNew->pManFunc ); + // make the network minimum base + Abc_NtkMinimumBase( pNtkNew ); // 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; - } + Abc_NtkBddToSop( pNtkNew ); return pNtkNew; -// return NULL; } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c index 9c9bbcfd..55d6cf7d 100644 --- a/src/base/abci/abcVerify.c +++ b/src/base/abci/abcVerify.c @@ -20,17 +20,13 @@ #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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -44,32 +40,27 @@ extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, SeeAlso [] ***********************************************************************/ -void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ) +void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) { - 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 ); + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) + if ( RetValue == 1 ) { - 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 ); + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); return; } - if ( RetValue == 1 ) + if ( RetValue == 0 ) { Abc_NtkDelete( pMiter ); printf( "Networks are equivalent after structural hashing.\n" ); @@ -77,7 +68,7 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI } // convert the miter into a CNF - pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); + pCnf = Abc_NtkRenode( pMiter, 0, 100, 1, 0, 0 ); Abc_NtkDelete( pMiter ); if ( pCnf == NULL ) { @@ -86,16 +77,10 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI } // 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 ) + if ( Abc_NtkMiterSat( pCnf, 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 ); } @@ -111,329 +96,52 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI SeeAlso [] ***********************************************************************/ -void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) +void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fVerbose ) { - Prove_Params_t Params, * pParams = &Params; -// Fraig_Params_t Params; -// Fraig_Man_t * pMan; + Fraig_Params_t Params; Abc_Ntk_t * pMiter; + Abc_Ntk_t * pFraig; int RetValue; // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 ); + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 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 ); + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); 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) ); + // convert the miter into a FRAIG + Fraig_ParamsSetDefault( &Params ); + Params.fVerbose = fVerbose; + pFraig = Abc_NtkFraig( pMiter, &Params, 0 ); 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 ) + if ( pFraig == NULL ) { - printf( "Miter computation has failed.\n" ); + printf( "Fraiging has failed.\n" ); return; } - RetValue = Abc_NtkMiterIsConstant( pMiter ); + RetValue = Abc_NtkMiterIsConstant( pFraig ); + Abc_NtkDelete( pFraig ); 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 ); + printf( "Networks are equivalent after fraiging.\n" ); 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 ); + printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); } /**Function************************************************************* @@ -447,29 +155,28 @@ void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds SeeAlso [] ***********************************************************************/ -void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ) +void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, 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 ); + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) + if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); return; } - if ( RetValue == 1 ) + if ( RetValue == 0 ) { Abc_NtkDelete( pMiter ); printf( "Networks are equivalent after structural hashing.\n" ); @@ -485,13 +192,13 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI return; } RetValue = Abc_NtkMiterIsConstant( pFrames ); - if ( RetValue == 0 ) + if ( RetValue == 1 ) { Abc_NtkDelete( pFrames ); printf( "Networks are NOT EQUIVALENT after framing.\n" ); return; } - if ( RetValue == 1 ) + if ( RetValue == 0 ) { Abc_NtkDelete( pFrames ); printf( "Networks are equivalent after framing.\n" ); @@ -499,7 +206,7 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI } // convert the miter into a CNF - pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 ); + pCnf = Abc_NtkRenode( pFrames, 0, 100, 1, 0, 0 ); Abc_NtkDelete( pFrames ); if ( pCnf == NULL ) { @@ -508,10 +215,7 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI } // 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 ) + if ( Abc_NtkMiterSat( pCnf, 0 ) ) printf( "Networks are NOT EQUIVALENT after SAT.\n" ); else printf( "Networks are equivalent after SAT.\n" ); @@ -529,37 +233,33 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI SeeAlso [] ***********************************************************************/ -int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ) +void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames ) { Fraig_Params_t Params; - Fraig_Man_t * pMan; Abc_Ntk_t * pMiter; + Abc_Ntk_t * pFraig; Abc_Ntk_t * pFrames; int RetValue; // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); - return 0; + return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) + if ( RetValue == 1 ) { - 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; + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + return; } - if ( RetValue == 1 ) + if ( RetValue == 0 ) { Abc_NtkDelete( pMiter ); printf( "Networks are equivalent after structural hashing.\n" ); - return 1; + return; } // create the timeframes @@ -568,446 +268,39 @@ int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFr if ( pFrames == NULL ) { printf( "Frames computation has failed.\n" ); - return 0; + return; } RetValue = Abc_NtkMiterIsConstant( pFrames ); - if ( RetValue == 0 ) + if ( RetValue == 1 ) { - 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; + printf( "Networks are NOT EQUIVALENT after framing.\n" ); + return; } - if ( RetValue == 1 ) + if ( RetValue == 0 ) { Abc_NtkDelete( pFrames ); printf( "Networks are equivalent after framing.\n" ); - return 1; + 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( 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 ); + pFraig = Abc_NtkFraig( pFrames, &Params, 0 ); 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 ( pFraig == NULL ) { - 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 ); + printf( "Fraiging has failed.\n" ); 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++ ) + RetValue = Abc_NtkMiterIsConstant( pFraig ); + Abc_NtkDelete( pFraig ); + if ( RetValue == 0 ) { - 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" ); + printf( "Networks are equivalent after fraiging.\n" ); + return; } - 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 ); + printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); } diff --git a/src/base/abci/abcXsim.c b/src/base/abci/abcXsim.c deleted file mode 100644 index e5656170..00000000 --- a/src/base/abci/abcXsim.c +++ /dev/null @@ -1,224 +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_NtkForEachLatch( pNtk, pObj, i ) -// Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 ); - Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) ); - // simulate for the given number of timeframes - for ( f = 0; f < nFrames; f++ ) - { - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); - 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) ); - 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 index 75ec88c3..bef3836f 100644 --- a/src/base/abci/abc_.c +++ b/src/base/abci/abc_.c @@ -23,9 +23,9 @@ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// - + //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -40,7 +40,6 @@ ***********************************************************************/ - //////////////////////////////////////////////////////////////////////// /// 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 index 4558119e..d7c0add2 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -1,54 +1,24 @@ 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/abcCollapse.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 + src/base/abci/abcVerify.c diff --git a/src/base/abcs/abcRetime.c b/src/base/abcs/abcRetime.c new file mode 100644 index 00000000..13b8a926 --- /dev/null +++ b/src/base/abcs/abcRetime.c @@ -0,0 +1,203 @@ +/**CFile**************************************************************** + + FileName [abcSeqRetime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Peforms retiming for optimal clock cycle.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSeqRetime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// storing arrival times in the nodes +static inline int Abc_NodeReadLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( (pNode)->pNtk->pData, (pNode)->Id ); } +static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( (pNode)->pNtk->pData, (pNode)->Id, (Value) ); } + +// the internal procedures +static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax ); +static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, int Fi ); +static int Abc_NodeUpdateLValue( Abc_Obj_t * pObj, int Fi ); + +// node status after updating its arrival time +enum { ABC_UPDATE_FAIL, ABC_UPDATE_NO, ABC_UPDATE_YES }; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Retimes AIG for optimal delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk ) +{ + int FiMax, FiBest; + assert( Abc_NtkIsSeq( pNtk ) ); + + // start storage for sequential arrival times + assert( pNtk->pData == NULL ); + pNtk->pData = Vec_IntAlloc( 0 ); + + // get the maximum possible clock + FiMax = Abc_NtkNodeNum(pNtk); + + // make sure this clock period is feasible + assert( Abc_NtkRetimeForPeriod( pNtk, FiMax ) ); + + // search for the optimal clock period between 0 and nLevelMax + FiBest = Abc_NtkRetimeSearch_rec( pNtk, 0, FiMax ); + // print the result + printf( "The best clock period is %3d.\n", FiBest ); + + // free storage + Vec_IntFree( pNtk->pData ); + pNtk->pData = NULL; +} + +/**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, int FiMin, int FiMax ) +{ + int Median; + + assert( FiMin < FiMax ); + if ( FiMin + 1 == FiMax ) + return FiMax; + + Median = FiMin + (FiMax - FiMin)/2; + + if ( Abc_NtkRetimeForPeriod( pNtk, Median ) ) + return Abc_NtkRetimeSearch_rec( pNtk, FiMin, Median ); // Median is feasible + else + return Abc_NtkRetimeSearch_rec( pNtk, Median, FiMax ); // 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, int Fi ) +{ + Vec_Ptr_t * vFrontier; + Abc_Obj_t * pObj, * pFanout; + int RetValue, i, k; + + // set l-values of all nodes to be minus infinity + Vec_IntFill( pNtk->pData, Abc_NtkObjNumMax(pNtk), -ABC_INFINITY ); + + // start the frontier by including PI fanouts + vFrontier = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Abc_NodeSetLValue( pObj, 0 ); + Abc_ObjForEachFanout( pObj, pFanout, k ) + if ( pFanout->fMarkA == 0 ) + { + Vec_PtrPush( vFrontier, pFanout ); + pFanout->fMarkA = 1; + } + } + + // iterate until convergence + Vec_PtrForEachEntry( vFrontier, pObj, i ) + { + RetValue = Abc_NodeUpdateLValue( pObj, Fi ); + if ( RetValue == ABC_UPDATE_FAIL ) + break; + // unmark the node as processed + pObj->fMarkA = 0; + if ( RetValue == ABC_UPDATE_NO ) + continue; + assert( RetValue == ABC_UPDATE_YES ); + // arrival times have changed - add fanouts to the frontier + Abc_ObjForEachFanout( pObj, pFanout, k ) + if ( pFanout->fMarkA == 0 ) + { + Vec_PtrPush( vFrontier, pFanout ); + pFanout->fMarkA = 1; + } + } + // clean the nodes + Vec_PtrForEachEntryStart( vFrontier, pObj, k, i ) + pObj->fMarkA = 0; + + // report the results + if ( RetValue == ABC_UPDATE_FAIL ) + printf( "Period = %3d. Updated nodes = %6d. Infeasible\n", Fi, vFrontier->nSize ); + else + printf( "Period = %3d. Updated nodes = %6d. Feasible\n", Fi, vFrontier->nSize ); + Vec_PtrFree( vFrontier ); + return RetValue != ABC_UPDATE_FAIL; +} + +/**Function************************************************************* + + Synopsis [Computes the l-value of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeUpdateLValue( Abc_Obj_t * pObj, int Fi ) +{ + int lValueNew, lValue0, lValue1; + assert( !Abc_ObjIsPi(pObj) ); + lValue0 = Abc_NodeReadLValue(Abc_ObjFanin0(pObj)) - Fi * Abc_ObjFaninL0(pObj); + if ( Abc_ObjFaninNum(pObj) == 2 ) + lValue1 = Abc_NodeReadLValue(Abc_ObjFanin1(pObj)) - Fi * Abc_ObjFaninL1(pObj); + else + lValue1 = -ABC_INFINITY; + lValueNew = 1 + ABC_MAX( lValue0, lValue1 ); + if ( Abc_ObjIsPo(pObj) && lValueNew > Fi ) + return ABC_UPDATE_FAIL; + if ( lValueNew == Abc_NodeReadLValue(pObj) ) + return ABC_UPDATE_NO; + Abc_NodeSetLValue( pObj, lValueNew ); + return ABC_UPDATE_YES; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/base/abcs/abcSeq.c b/src/base/abcs/abcSeq.c new file mode 100644 index 00000000..a41edac1 --- /dev/null +++ b/src/base/abcs/abcSeq.c @@ -0,0 +1,642 @@ +/**CFile**************************************************************** + + FileName [abcSeq.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: abcSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + A sequential network is an AIG whose edges have number-of-latches attributes, + in addition to the complemented attibutes. + + The sets of PIs/POs remain the same as in logic network. + Constant 1 node can only be used as a fanin of a PO node and the reset node. + The reset node produces sequence (01111...). It is used to create the + initialization logic of all latches. + The latches do not have explicit initial state but they are implicitly + reset by the reset node. + +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Vec_Int_t * Abc_NtkSeqCountLatches( Abc_Ntk_t * pNtk ); +static void Abc_NodeSeqCountLatches( Abc_Obj_t * pObj, Vec_Int_t * vNumbers ); + +static void Abc_NtkSeqCreateLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static void Abc_NodeSeqCreateLatches( Abc_Obj_t * pObj, int nLatches ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts a normal AIG into a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Aig_t * pManNew; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pConst, * pFanout, * pFaninNew, * pLatch; + int i, k, fChange, Counter; + + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_SEQ, ABC_FUNC_AIG ); + pManNew = pNtkNew->pManFunc; + + // set mapping of the constant nodes + Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1( pManNew ); + Abc_AigReset(pNtk->pManFunc)->pCopy = Abc_AigReset( pManNew ); + + // get rid of initial states + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pObj->pNext = pObj->pCopy; + if ( Abc_LatchIsInit0(pObj) ) + pObj->pCopy = Abc_AigAnd( pManNew, pObj->pCopy, Abc_AigReset(pManNew) ); + else if ( Abc_LatchIsInit1(pObj) ) + pObj->pCopy = Abc_AigOr( pManNew, pObj->pCopy, Abc_ObjNot( Abc_AigReset(pManNew) ) ); + } + + // copy internal nodes + vNodes = Abc_AigDfs( pNtk, 1, 0 ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( Abc_ObjFaninNum(pObj) == 2 ) + pObj->pCopy = Abc_AigAnd( pManNew, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + + // relink the CO nodes + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pNext, Abc_ObjChild0Copy(pObj) ); + + // propagate constant input latches in the new network + Counter = 0; + fChange = 1; + while ( fChange ) + { + fChange = 0; + Abc_NtkForEachLatch( pNtkNew, pLatch, i ) + { + if ( Abc_ObjFanoutNum(pLatch) == 0 ) + continue; + pFaninNew = Abc_ObjFanin0(pLatch); + if ( Abc_ObjIsCi(pFaninNew) || !Abc_NodeIsConst(pFaninNew) ) + continue; + pConst = Abc_ObjNotCond( Abc_AigConst1(pManNew), Abc_ObjFaninC0(pLatch) ); + Abc_AigReplace( pManNew, pLatch, pConst ); + fChange = 1; + Counter++; + } + } + if ( Counter ) + fprintf( stdout, "Latch sweeping removed %d latches (out of %d).\n", Counter, Abc_NtkLatchNum(pNtk) ); + + // redirect fanouts of each latch to the latch fanins + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachLatch( pNtkNew, pLatch, i ) + { +//printf( "Latch %s. Fanouts = %d.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) ); + + Abc_NodeCollectFanouts( pLatch, vNodes ); + Vec_PtrForEachEntry( vNodes, pFanout, k ) + { + if ( Abc_ObjFaninId0(pFanout) == Abc_ObjFaninId1(pFanout)) + printf( " ******* Identical fanins!!! ******* \n" ); + + if ( Abc_ObjFaninId0(pFanout) == (int)pLatch->Id ) + { +// pFaninNew = Abc_ObjNotCond( Abc_ObjChild0(pLatch), Abc_ObjFaninC0(pFanout) ); + pFaninNew = Abc_ObjChild0(pLatch); + Abc_ObjPatchFanin( pFanout, pLatch, pFaninNew ); + Abc_ObjAddFaninL0( pFanout, 1 ); + } + else if ( Abc_ObjFaninId1(pFanout) == (int)pLatch->Id ) + { +// pFaninNew = Abc_ObjNotCond( Abc_ObjChild0(pLatch), Abc_ObjFaninC1(pFanout) ); + pFaninNew = Abc_ObjChild0(pLatch); + Abc_ObjPatchFanin( pFanout, pLatch, pFaninNew ); + Abc_ObjAddFaninL1( pFanout, 1 ); + } + else + assert( 0 ); + } + assert( Abc_ObjFanoutNum(pLatch) == 0 ); + Abc_NtkDeleteObj( pLatch ); + } + Vec_PtrFree( vNodes ); + // get rid of latches altogether +// Abc_NtkForEachLatch( pNtkNew, pObj, i ) +// Abc_NtkDeleteObj( pObj ); + assert( pNtkNew->nLatches == 0 ); + Vec_PtrClear( pNtkNew->vLats ); + Vec_PtrShrink( pNtkNew->vCis, pNtk->nPis ); + Vec_PtrShrink( pNtkNew->vCos, pNtk->nPos ); + +/* +///////////////////////////////////////////// +Abc_NtkForEachNode( pNtkNew, pObj, i ) + if ( !Abc_NodeIsConst(pObj) ) + if ( Abc_ObjFaninL0(pObj) + Abc_ObjFaninL1(pObj) > 20 ) + printf( "(%d,%d) ", Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) ); +Abc_NtkForEachCo( pNtkNew, pObj, i ) + printf( "(%d) ", Abc_ObjFaninL0(pObj) ); +///////////////////////////////////////////// +printf( "\n" ); +*/ + + if ( pNtk->pExdc ) + fprintf( stdout, "Warning: EXDC is dropped when converting to sequential AIG.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToSeq(): 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( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pFaninNew; + int i, k, c; + assert( Abc_NtkIsSeq(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP ); + // create the constant and reset nodes + Abc_NtkDupConst1( pNtk, pNtkNew ); + Abc_NtkDupReset( pNtk, pNtkNew ); + // duplicate the nodes, create node functions and latches + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( Abc_NodeIsConst(pObj) ) + continue; + Abc_NtkDupObj(pNtkNew, pObj); + pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + } + // create latches for the new nodes + Abc_NtkSeqCreateLatches( pNtk, pNtkNew ); + // connect the objects + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + // find the fanin + pFaninNew = pFanin->pCopy; + for ( c = 0; c < Abc_ObjFaninL(pObj, k); c++ ) + pFaninNew = pFaninNew->pCopy; + Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); + } + // set the complemented attributed of CO edges (to be fixed by making simple COs) + Abc_NtkForEachPo( pNtk, pObj, i ) + if ( Abc_ObjFaninC0(pObj) ) + Abc_ObjSetFaninC( pObj->pCopy, 0 ); + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate the EXDC network + if ( pNtk->pExdc ) + fprintf( stdout, "Warning: EXDC network is not copied.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkSeqToLogic(): Network check has failed.\n" ); + return pNtkNew; +} + + + + +/**Function************************************************************* + + Synopsis [Finds max number of latches on the fanout edges of each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkSeqCountLatches( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vNumbers; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsSeq( pNtk ) ); + // start the array of counters + vNumbers = Vec_IntAlloc( 0 ); + Vec_IntFill( vNumbers, Abc_NtkObjNumMax(pNtk), 0 ); + // count for each edge + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_NodeSeqCountLatches( pObj, vNumbers ); + return vNumbers; +} + +/**Function************************************************************* + + Synopsis [Countes the latch numbers due to the fanins edges of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSeqCountLatches( Abc_Obj_t * pObj, Vec_Int_t * vNumbers ) +{ + Abc_Obj_t * pFanin; + int k, nLatches; + // go through each fanin edge + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + nLatches = Abc_ObjFaninL( pObj, k ); + if ( nLatches == 0 ) + continue; + if ( Vec_IntEntry( vNumbers, pFanin->Id ) < nLatches ) + Vec_IntWriteEntry( vNumbers, pFanin->Id, nLatches ); + } +} + + + +/**Function************************************************************* + + Synopsis [Creates latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSeqCreateLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Vec_Int_t * vNumbers; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsSeq( pNtk ) ); + // create latches for each new object according to the counters + vNumbers = Abc_NtkSeqCountLatches( pNtk ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy == NULL ) + continue; + Abc_NodeSeqCreateLatches( pObj->pCopy, Vec_IntEntry(vNumbers, (int)pObj->Id) ); + } + Vec_IntFree( vNumbers ); + // add latch to the PI/PO lists, create latch names + Abc_NtkFinalizeLatches( pNtkNew ); +} + +/**Function************************************************************* + + Synopsis [Creates the given number of latches for this object.] + + Description [The latches are attached to the node and to each other + through the pCopy field.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSeqCreateLatches( Abc_Obj_t * pObj, int nLatches ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + Abc_Obj_t * pLatch, * pFanin; + int i; + pFanin = pObj; + for ( i = 0, pFanin = pObj; i < nLatches; pFanin = pLatch, i++ ) + { + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_LatchSetInitDc(pLatch); + Abc_ObjAddFanin( pLatch, pFanin ); + pFanin->pCopy = pLatch; + } +} + +/**Function************************************************************* + + Synopsis [Counters the number of latches in the sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSeqLatchNum( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vNumbers; + Abc_Obj_t * pObj; + int i, Counter; + assert( Abc_NtkIsSeq( pNtk ) ); + // create latches for each new object according to the counters + Counter = 0; + vNumbers = Abc_NtkSeqCountLatches( pNtk ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + assert( Abc_ObjFanoutLMax(pObj) == Vec_IntEntry(vNumbers, (int)pObj->Id) ); + Counter += Vec_IntEntry(vNumbers, (int)pObj->Id); + } + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( Abc_NodeIsConst(pObj) ) + continue; + assert( Abc_ObjFanoutLMax(pObj) == Vec_IntEntry(vNumbers, (int)pObj->Id) ); + Counter += Vec_IntEntry(vNumbers, (int)pObj->Id); + } + Vec_IntFree( vNumbers ); + if ( Abc_ObjFanoutNum( Abc_AigReset(pNtk->pManFunc) ) > 0 ) + Counter++; + return Counter; +} + + + + + + +/**Function************************************************************* + + Synopsis [Performs forward retiming of the sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSeqRetimeForward( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanout; + int i, k, nLatches; + assert( Abc_NtkIsSeq( pNtk ) ); + // assume that all nodes can be retimed + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + Vec_PtrPush( vNodes, pNode ); + pNode->fMarkA = 1; + } + // process the nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { +// printf( "(%d,%d) ", Abc_ObjFaninL0(pNode), Abc_ObjFaninL0(pNode) ); + // get the number of latches to retime + nLatches = Abc_ObjFaninLMin(pNode); + if ( nLatches == 0 ) + continue; + assert( nLatches > 0 ); + // subtract these latches on the fanin side + Abc_ObjAddFaninL0( pNode, -nLatches ); + Abc_ObjAddFaninL1( pNode, -nLatches ); + // add these latches on the fanout size + Abc_ObjForEachFanout( pNode, pFanout, k ) + { + Abc_ObjAddFanoutL( pNode, pFanout, nLatches ); + if ( pFanout->fMarkA == 0 ) + { // schedule the node for updating + Vec_PtrPush( vNodes, pFanout ); + pFanout->fMarkA = 1; + } + } + // unmark the node as processed + pNode->fMarkA = 0; + } + Vec_PtrFree( vNodes ); + // clean the marks + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pNode->fMarkA = 0; + if ( Abc_NodeIsConst(pNode) ) + continue; + assert( Abc_ObjFaninLMin(pNode) == 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Performs forward retiming of the sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin, * pFanout; + int i, k, nLatches; + assert( Abc_NtkIsSeq( pNtk ) ); + // assume that all nodes can be retimed + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + Vec_PtrPush( vNodes, pNode ); + pNode->fMarkA = 1; + } + // process the nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + // get the number of latches to retime + nLatches = Abc_ObjFanoutLMin(pNode); + if ( nLatches == 0 ) + continue; + assert( nLatches > 0 ); + // subtract these latches on the fanout side + Abc_ObjForEachFanout( pNode, pFanout, k ) + Abc_ObjAddFanoutL( pNode, pFanout, -nLatches ); + // add these latches on the fanin size + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + Abc_ObjAddFaninL( pNode, k, nLatches ); + if ( Abc_ObjIsPi(pFanin) || Abc_NodeIsConst(pFanin) ) + continue; + if ( pFanin->fMarkA == 0 ) + { // schedule the node for updating + Vec_PtrPush( vNodes, pFanin ); + pFanin->fMarkA = 1; + } + } + // unmark the node as processed + pNode->fMarkA = 0; + } + Vec_PtrFree( vNodes ); + // clean the marks + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pNode->fMarkA = 0; + if ( Abc_NodeIsConst(pNode) ) + continue; +// assert( Abc_ObjFanoutLMin(pNode) == 0 ); + } +} + + + + +/**Function************************************************************* + + Synopsis [Returns the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) +{ + assert( Abc_NtkIsSeq(pObj->pNtk) ); + if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id ) + return Abc_ObjFaninL0(pFanout); + else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id ) + return Abc_ObjFaninL1(pFanout); + else + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Sets the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ) +{ + assert( Abc_NtkIsSeq(pObj->pNtk) ); + if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id ) + Abc_ObjSetFaninL0(pFanout, nLats); + else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id ) + Abc_ObjSetFaninL1(pFanout, nLats); + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Adds to the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ) +{ + assert( Abc_NtkIsSeq(pObj->pNtk) ); + if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id ) + Abc_ObjAddFaninL0(pFanout, nLats); + else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id ) + Abc_ObjAddFaninL1(pFanout, nLats); + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Returns the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutLMax( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, nLatch, nLatchRes; + nLatchRes = 0; + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( nLatchRes < (nLatch = Abc_ObjFanoutL(pObj, pFanout)) ) + nLatchRes = nLatch; + assert( nLatchRes >= 0 ); + return nLatchRes; +} + +/**Function************************************************************* + + Synopsis [Returns the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutLMin( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, nLatch, nLatchRes; + nLatchRes = ABC_INFINITY; + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( nLatchRes > (nLatch = Abc_ObjFanoutL(pObj, pFanout)) ) + nLatchRes = nLatch; + assert( nLatchRes < ABC_INFINITY ); + return nLatchRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abcs/abc_.c b/src/base/abcs/abc_.c new file mode 100644 index 00000000..bef3836f --- /dev/null +++ b/src/base/abcs/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 DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abcs/module.make b/src/base/abcs/module.make new file mode 100644 index 00000000..ad084bb8 --- /dev/null +++ b/src/base/abcs/module.make @@ -0,0 +1,2 @@ +SRC += src/base/abcs/abcRetime.c \ + src/base/abcs/abcSeq.c diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 2dc03d5c..9195554a 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -18,10 +18,6 @@ ***********************************************************************/ -#ifdef WIN32 -#include -#endif - #include "mainInt.h" #include "cmdInt.h" #include "abc.h" @@ -49,10 +45,9 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** @@ -90,7 +85,6 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1); Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1); - Cmd_CommandAdd( pAbc, "Various", "capo", CmdCommandCapo, 0); } /**Function******************************************************************** @@ -148,8 +142,8 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -160,7 +154,7 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) } } - if ( argc != globalUtilOptind ) + if ( argc != util_optind ) { goto usage; } @@ -168,14 +162,6 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) 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; @@ -202,8 +188,8 @@ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv ) int c; int n = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "hn" ) ) != EOF ) { switch ( c ) { @@ -218,7 +204,7 @@ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv ) } } - for ( i = globalUtilOptind; i < argc; i++ ) + for ( i = util_optind; i < argc; i++ ) fprintf( pAbc->Out, "%s ", argv[i] ); if ( n ) fprintf( pAbc->Out, "\n" ); @@ -248,8 +234,8 @@ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "hs" ) ) != EOF ) { switch ( c ) { @@ -264,7 +250,7 @@ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv ) } } - if ( argc != globalUtilOptind ) + if ( argc != util_optind ) goto usage; return -1; @@ -308,8 +294,8 @@ 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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -323,8 +309,8 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) goto usage; // get the number of commands to print - if ( argc == globalUtilOptind + 1 ) - num = atoi(argv[globalUtilOptind]); + if ( argc == util_optind + 1 ) + num = atoi(argv[util_optind]); // print the commands size = pAbc->aHistory->nSize; num = ( num < size ) ? num : size; @@ -356,8 +342,8 @@ 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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -413,8 +399,8 @@ int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv ) char *key, *value; int c; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -464,8 +450,8 @@ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv ) int c; fPrintAll = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ah" ) ) != EOF ) { switch ( c ) { @@ -482,7 +468,7 @@ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv ) } } - if ( argc != globalUtilOptind ) + if ( argc != util_optind ) goto usage; CmdCommandPrint( pAbc, fPrintAll ); @@ -517,37 +503,38 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) interactive = silent = prompt = echo = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ipsxh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "hipsx" ) ) != EOF ) { switch ( c ) { + case 'h': + goto usage; + break; case 'i': /* a hack to distinguish EOF from stdin */ interactive = 1; break; case 'p': - prompt ^= 1; + prompt = 1; break; case 's': - silent ^= 1; + 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 ) + if ( argc == util_optind ) { goto usage; } - lp_file_index = globalUtilOptind; + lp_file_index = util_optind; lp_count = 0; /* @@ -581,7 +568,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) } else { - prompt_string = NULL; + prompt_string = NIL( char ); } /* clear errors -- e.g., EOF reached from stdin */ @@ -615,7 +602,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pAbc->Out, "abc - > %s", line ); } command = CmdHistorySubstitution( pAbc, line, &did_subst ); - if ( command == NULL ) + if ( command == NIL( char ) ) { status = 1; break; @@ -633,8 +620,8 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) } if ( interactive && *line != '\0' ) { - Cmd_HistoryAddCommand( pAbc, Extra_UtilStrsav(line) ); - if ( pAbc->Hst != NULL ) + Cmd_HistoryAddCommand( pAbc, util_strsav(line) ); + if ( pAbc->Hst != NIL( FILE ) ) { fprintf( pAbc->Hst, "%s\n", line ); ( void ) fflush( pAbc->Hst ); @@ -663,11 +650,11 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) 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, "usage: source [-h] [-p] [-s] [-x] file_name\n" ); fprintf( pAbc->Err, "\t-h print the command usage\n" ); + fprintf( pAbc->Err, "\t-p supply prompt before reading each line\n" ); + fprintf( pAbc->Err, "\t-s silently ignore nonexistant file\n" ); + fprintf( pAbc->Err, "\t-x echo each line as it is executed\n" ); return 1; } @@ -687,8 +674,8 @@ 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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -716,9 +703,9 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) 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 ); + flag_value = argc == 2 ? util_strsav( "" ) : util_strsav( argv[2] ); +// flag_value = argc == 2 ? NULL : util_strsav(argv[2]); + st_insert( pAbc->tFlags, util_strsav(argv[1]), flag_value ); if ( strcmp( argv[1], "abcout" ) == 0 ) { @@ -726,7 +713,7 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) fclose( pAbc->Out ); if ( strcmp( flag_value, "" ) == 0 ) flag_value = "-"; - pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 ); if ( pAbc->Out == NULL ) pAbc->Out = stdout; #if HAVE_SETVBUF @@ -739,7 +726,7 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) fclose( pAbc->Err ); if ( strcmp( flag_value, "" ) == 0 ) flag_value = "-"; - pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 ); if ( pAbc->Err == NULL ) pAbc->Err = stderr; #if HAVE_SETVBUF @@ -748,15 +735,15 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) } if ( strcmp( argv[1], "history" ) == 0 ) { - if ( pAbc->Hst != NULL ) + if ( pAbc->Hst != NIL( FILE ) ) fclose( pAbc->Hst ); if ( strcmp( flag_value, "" ) == 0 ) - pAbc->Hst = NULL; + pAbc->Hst = NIL( FILE ); else { - pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 ); if ( pAbc->Hst == NULL ) - pAbc->Hst = NULL; + pAbc->Hst = NIL( FILE ); } } return 0; @@ -787,8 +774,8 @@ int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) char *key, *value; int c; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -880,8 +867,8 @@ int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv ) } - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -992,8 +979,8 @@ int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1034,7 +1021,7 @@ 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 ) + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1045,12 +1032,12 @@ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) goto usage; } } - if (globalUtilOptind <= argc) { + if (util_optind <= argc) { pNtkTemp = pAbc->pNtk; pAbc->pNtk = pAbc->pNtkSaved; pAbc->pNtkSaved = pNtkTemp; } - id = atoi(argv[globalUtilOptind]); + id = atoi(argv[util_optind]); pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id); if (!pNtkTemp) fprintf( pAbc->Err, "Snapshot %d does not exist\n", id); @@ -1108,8 +1095,8 @@ int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv ) int fPrintedNewLine; char c; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF ) + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "lb") ) != EOF ) { switch (c) { @@ -1217,7 +1204,7 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) char * pSisName; int i; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); @@ -1258,21 +1245,8 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) } 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; - } + pNetlist = Abc_NtkLogicToNetlist(pNtk); Io_WriteBlif( pNetlist, "_sis_in.blif", 1 ); Abc_NtkDelete( pNetlist ); @@ -1309,12 +1283,12 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) fclose( pFile ); // set the new network - pNtkNew = Io_Read( "_sis_out.blif", IO_FILE_BLIF, 1 ); + pNtkNew = Io_Read( "_sis_out.blif", 1 ); // set the original spec of the new network if ( pNtk->pSpec ) { FREE( pNtkNew->pSpec ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + pNtkNew->pSpec = util_strsav( pNtk->pSpec ); } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); @@ -1360,7 +1334,7 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) char * pMvsisName; int i; - pNtk = Abc_FrameReadNtk(pAbc); + pNtk = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); @@ -1401,21 +1375,9 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) } 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; - } + pNetlist = Abc_NtkLogicToNetlist(pNtk); Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1 ); Abc_NtkDelete( pNetlist ); @@ -1452,12 +1414,12 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) fclose( pFile ); // set the new network - pNtkNew = Io_Read( "_mvsis_out.blif", IO_FILE_BLIF, 1 ); + pNtkNew = Io_Read( "_mvsis_out.blif", 1 ); // set the original spec of the new network if ( pNtk->pSpec ) { FREE( pNtkNew->pSpec ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + pNtkNew->pSpec = util_strsav( pNtk->pSpec ); } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); @@ -1481,192 +1443,6 @@ usage: } -/**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 index 030b77e8..6389afae 100644 --- a/src/base/cmd/cmd.h +++ b/src/base/cmd/cmd.h @@ -21,10 +21,6 @@ #ifndef __CMD_H__ #define __CMD_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -41,11 +37,11 @@ typedef struct MvCommand Abc_Command; // one command typedef struct MvAlias Abc_Alias; // one alias //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== cmd.c ===========================================================*/ @@ -61,13 +57,9 @@ extern void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * v /*=== cmdHist.c ========================================================*/ extern void Cmd_HistoryAddCommand( Abc_Frame_t * pAbc, char * command ); -#ifdef __cplusplus -} -#endif - -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/base/cmd/cmdAlias.c b/src/base/cmd/cmdAlias.c index 0ec3feea..59a8b87e 100644 --- a/src/base/cmd/cmdAlias.c +++ b/src/base/cmd/cmdAlias.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -45,11 +45,11 @@ void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** arg int fStatus, i; pAlias = ALLOC(Abc_Alias, 1); - pAlias->sName = Extra_UtilStrsav(sName); + pAlias->sName = util_strsav(sName); pAlias->argc = argc; pAlias->argv = ALLOC(char *, pAlias->argc); for(i = 0; i < argc; i++) - pAlias->argv[i] = Extra_UtilStrsav(argv[i]); + pAlias->argv[i] = util_strsav(argv[i]); fStatus = st_insert( pAbc->tAliases, pAlias->sName, (char *) pAlias ); assert(!fStatus); } diff --git a/src/base/cmd/cmdApi.c b/src/base/cmd/cmdApi.c index 7167e22b..8dd67637 100644 --- a/src/base/cmd/cmdApi.c +++ b/src/base/cmd/cmdApi.c @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -57,8 +57,8 @@ void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFu // create the new command pCommand = ALLOC( Abc_Command, 1 ); - pCommand->sName = Extra_UtilStrsav( sName ); - pCommand->sGroup = Extra_UtilStrsav( sGroup ); + pCommand->sName = util_strsav( sName ); + pCommand->sGroup = util_strsav( sGroup ); pCommand->pFunc = pFunc; pCommand->fChange = fChanges; fStatus = st_insert( pAbc->tCommands, sName, (char *)pCommand ); diff --git a/src/base/cmd/cmdFlag.c b/src/base/cmd/cmdFlag.c index 993f2a49..63a0389d 100644 --- a/src/base/cmd/cmdFlag.c +++ b/src/base/cmd/cmdFlag.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// @@ -35,7 +35,8 @@ 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.] + named flag is returned, or NIL(char) is returned if the flag has not been + set.] SideEffects [] @@ -64,9 +65,9 @@ void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value ) if ( !key ) return; if ( value ) - newValue = Extra_UtilStrsav(value); + newValue = util_strsav(value); else - newValue = Extra_UtilStrsav(""); + newValue = util_strsav(""); // newValue = NULL; if ( st_delete(pAbc->tFlags, &key, &oldValue) ) FREE(oldValue); diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c index fae9382d..5b46ea00 100644 --- a/src/base/cmd/cmdHist.c +++ b/src/base/cmd/cmdHist.c @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -43,11 +43,11 @@ ***********************************************************************/ void Cmd_HistoryAddCommand( Abc_Frame_t * p, char * command ) { - static char Buffer[MAX_STR]; + char Buffer[500]; strcpy( Buffer, command ); if ( command[strlen(command)-1] != '\n' ) strcat( Buffer, "\n" ); - Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) ); + Vec_PtrPush( p->aHistory, util_strsav(Buffer) ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/cmd/cmdInt.h b/src/base/cmd/cmdInt.h index c082bd94..d110b634 100644 --- a/src/base/cmd/cmdInt.h +++ b/src/base/cmd/cmdInt.h @@ -52,11 +52,11 @@ struct MvAlias }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== cmdAlias.c =============-========================================*/ diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c index 47e54bb3..71396d3e 100644 --- a/src/base/cmd/cmdUtils.c +++ b/src/base/cmd/cmdUtils.c @@ -30,7 +30,7 @@ static int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -121,10 +121,10 @@ int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char **argv ) } // execute the command - clk = Extra_CpuTime(); + clk = util_cpu_time(); pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc; fError = (*pFunc)( pAbc, argc, argv ); - pAbc->TimeCommand += (Extra_CpuTime() - clk); + pAbc->TimeCommand += (util_cpu_time() - clk); // automatic execution of arbitrary command after each command // usually this is a passive command ... @@ -245,7 +245,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) argc = *argcp; argv = *argvp; stopit = 0; - for ( ; *loop < 200; ( *loop )++ ) + for ( ; *loop < 20; ( *loop )++ ) { if ( argc == 0 ) return 0; @@ -270,7 +270,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) } for ( i = 1; i <= added; i++ ) { - argv[i] = NULL; + argv[i] = NIL( char ); } argc += added; } @@ -278,7 +278,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) for ( i = 0, offset = 0; i < alias->argc; i++, offset++ ) { arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst ); - if ( arg == NULL ) + if ( arg == NIL( char ) ) { *argcp = argc; *argvp = argv; @@ -383,11 +383,11 @@ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFi if (strcmp(sFileName, "-") == 0) { if (strcmp(sMode, "w") == 0) { - sRealName = Extra_UtilStrsav( "stdout" ); + sRealName = util_strsav( "stdout" ); pFile = stdout; } else { - sRealName = Extra_UtilStrsav( "stdin" ); + sRealName = util_strsav( "stdin" ); pFile = stdin; } } @@ -403,24 +403,24 @@ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFi sPathAll = NULL; } else if ( sPathUsr == NULL ) { - sPathAll = Extra_UtilStrsav( sPathLib ); + sPathAll = util_strsav( sPathLib ); } else if ( sPathLib == NULL ) { - sPathAll = Extra_UtilStrsav( sPathUsr ); + sPathAll = util_strsav( 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"); + if ( sPathAll != NIL(char) ) { + sRealName = util_file_search(sFileName, sPathAll, "r"); FREE( sPathAll ); } } - if (sRealName == NULL) { - sRealName = Extra_UtilTildeExpand(sFileName); + if (sRealName == NIL(char)) { + sRealName = util_tilde_expand(sFileName); } - if ((pFile = fopen(sRealName, sMode)) == NULL) { + if ((pFile = fopen(sRealName, sMode)) == NIL(FILE)) { if (! silent) { perror(sRealName); } diff --git a/src/base/io/io.c b/src/base/io/io.c index fe88a285..89703214 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -26,43 +26,23 @@ //////////////////////////////////////////////////////////////////////// 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 IoCommandReadPla ( 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -79,38 +59,20 @@ extern int glo_fMapped; 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_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", "read_pla", IoCommandReadPla, 1 ); - 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************************************************************* @@ -142,20 +104,17 @@ void Io_End() int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; - char * pFileName; + char * FileName; + FILE * pFile; int fCheck; int c; fCheck = 1; - glo_fMapped = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { - case 'm': - glo_fMapped ^= 1; - break; case 'c': fCheck ^= 1; break; @@ -165,24 +124,38 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + if ( argc != util_optind + 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 ); + FileName = argv[util_optind]; + 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 + pNtk = Io_Read( FileName, fCheck ); if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Reading network from file has failed.\n" ); 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, "usage: read [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network from file in Verilog/BLIF/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" ); @@ -200,16 +173,17 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; - char * pFileName; + Abc_Ntk_t * pNtk, * pTemp; + char * FileName; + FILE * pFile; int fCheck; int c; fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -222,21 +196,47 @@ int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + if ( argc != util_optind + 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 ); + FileName = argv[util_optind]; + 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 + pNtk = Io_ReadBlif( FileName, fCheck ); if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Reading network from BLIF file has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" ); 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, "usage: read_blif [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in binary BLIF 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" ); @@ -254,16 +254,17 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; - char * pFileName; + Abc_Ntk_t * pNtk, * pTemp; + char * FileName; + FILE * pFile; int fCheck; int c; fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -276,21 +277,46 @@ int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + if ( argc != util_optind + 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 ); + FileName = argv[util_optind]; + 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 + pNtk = Io_ReadBench( FileName, fCheck ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Reading network from BENCH file has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" ); 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, "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" ); @@ -308,25 +334,20 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; - char * pFileName; - int fReadAsAig; + Abc_Ntk_t * pNtk, * pTemp; + char * FileName; + FILE * pFile; 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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { - case 'a': - fReadAsAig ^= 1; - break; case 'c': fCheck ^= 1; break; @@ -336,34 +357,46 @@ int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + if ( argc != util_optind + 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 ); + FileName = argv[util_optind]; + 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 + pNtk = Io_ReadEdif( FileName, fCheck ); + if ( pNtk == NULL ) { - Abc_Ntk_t * pTemp; - pNtk = Io_ReadBlif( pFileName, fCheck ); - if ( pNtk == NULL ) - return 1; - pNtk = Abc_NtkToLogic( pTemp = pNtk ); - Abc_NtkDelete( pTemp ); + fprintf( pAbc->Err, "Reading network from EDIF file has failed.\n" ); + return 1; } + pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" ); 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, "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" ); @@ -381,16 +414,17 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; - char * pFileName; + Abc_Ntk_t * pNtk, * pTemp; + char * FileName; + FILE * pFile; int fCheck; int c; fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -403,21 +437,46 @@ int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + if ( argc != util_optind + 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 ); + FileName = argv[util_optind]; + 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 + pNtk = Io_ReadEqn( FileName, fCheck ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Reading network from the equation file has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" ); 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, "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" ); @@ -435,16 +494,17 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; - char * pFileName; + Abc_Ntk_t * pNtk, * pTemp; + char * FileName; + FILE * pFile; int fCheck; int c; fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -457,21 +517,46 @@ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + if ( argc != util_optind + 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 ); + FileName = argv[util_optind]; + 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 + pNtk = Io_ReadVerilog( FileName, fCheck ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Reading network from the verilog file has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" ); 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, "usage: read_verilog [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in Verilog (IWLS 2005 subset)\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" ); @@ -489,17 +574,17 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; - char * pString; + Abc_Ntk_t * pNtk, * pTemp; + char * FileName; + FILE * pFile; int fCheck; int c; - extern Abc_Ntk_t * Io_ReadDsd( char * pFormula ); fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -512,33 +597,53 @@ int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + if ( argc != util_optind + 1 ) + { goto usage; + } + // get the input file name - pString = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_ReadDsd( pString ); + FileName = argv[util_optind]; + 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 + pNtk = Io_ReadPla( FileName, fCheck ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Reading network from PLA file has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" ); 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" ); + 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 [] @@ -550,21 +655,21 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; + char * FileName; + int fWriteLatches; int c; - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + fWriteLatches = 1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { - case 'c': - fCheck ^= 1; + case 'l': + fWriteLatches ^= 1; break; case 'h': goto usage; @@ -572,24 +677,36 @@ int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) 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 ); + + pNtk = pAbc->pNtkCur; if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( argc != util_optind + 1 ) + { + goto usage; + } + FileName = argv[util_optind]; + + // check the network type + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSeq(pNtk) ) + { + fprintf( pAbc->Out, "Currently can only write logic networks, AIGs, and seq AIGs.\n" ); + return 0; + } + Io_WriteBlifLogic( pNtk, FileName, fWriteLatches ); +// Io_WriteBlif( pNtk, FileName, fWriteLatches ); 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" ); + fprintf( pAbc->Err, "usage: write_blif [-lh] \n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); + fprintf( pAbc->Err, "\t-l : toggle writing latches [default = %s]\n", fWriteLatches? "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; } @@ -604,21 +721,21 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv ) { - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; + Abc_Ntk_t * pNtk, * pNtkTemp; + char * FileName; + int fWriteLatches; int c; - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + fWriteLatches = 1; + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { - case 'c': - fCheck ^= 1; + case 'l': + fWriteLatches ^= 1; break; case 'h': goto usage; @@ -626,24 +743,44 @@ int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( argc != util_optind + 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 ); + FileName = argv[util_optind]; + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pAbc->Out, "The network should be an AIG.\n" ); + return 0; + } + + // derive the netlist + pNtkTemp = Abc_NtkLogicToNetlistBench(pNtk); + if ( pNtkTemp == NULL ) + { + fprintf( pAbc->Out, "Writing BENCH has failed.\n" ); + return 0; + } + Io_WriteBench( pNtkTemp, FileName ); + Abc_NtkDelete( pNtkTemp ); 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" ); + fprintf( pAbc->Err, "usage: write_bench [-h] \n" ); + fprintf( pAbc->Err, "\t write the network in BENCH format\n" ); +// fprintf( pAbc->Err, "\t-l : toggle writing latches [default = %s]\n", fWriteLatches? "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; } @@ -658,20 +795,13 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv ) +int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv ) { - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - char * pFileName; + char * FileName; 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 ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -681,728 +811,33 @@ int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( argc != util_optind + 1 ) + { goto usage; + } - if ( pNtk == NULL ) + // get the input file name + FileName = argv[util_optind]; + // write the file + if ( !Io_WriteCnf( pAbc->pNtkCur, FileName ) ) { - fprintf( pErr, "Empty network.\n" ); + printf( "Writing CNF has failed.\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 fCompact; - int c; - - fCompact = 1; - fWriteSymbols = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "sch" ) ) != EOF ) - { - switch ( c ) - { - case 's': - fWriteSymbols ^= 1; - break; - case 'c': - fCompact ^= 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 ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) - { - fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); - return 1; - } - Io_WriteAiger( pAbc->pNtkCur, pFileName, fWriteSymbols, fCompact ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_aiger [-sch] \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-c : toggle writing more compactly [default = %s]\n", fCompact? "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, "usage: write_cnf [-h] \n" ); + fprintf( pAbc->Err, "\t write the miter cone into a CNF file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .bench)\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } @@ -1417,15 +852,14 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ) +int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) { - Abc_Ntk_t * pNtk; - char * pFileName; + char * FileName; + Vec_Ptr_t * vNodes; int c; - extern void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1435,145 +869,40 @@ int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) - goto usage; - pNtk = pAbc->pNtkCur; - if ( pNtk == NULL ) + + if ( pAbc->pNtkCur == 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) ) + + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) { - fprintf( pAbc->Out, "The network should be a logic network (if it an AIG, use command \"logic\")\n" ); + fprintf( stdout, "IoCommandWriteDot(): Currently can only process logic networks with BDDs.\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 ) + if ( argc != util_optind + 1 ) { - 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 ); + + // get the input file name + FileName = argv[util_optind]; + // write the file + vNodes = Abc_NtkCollectObjects( pAbc->pNtkCur ); + Io_WriteDot( pAbc->pNtkCur, vNodes, NULL, FileName ); + Vec_PtrFree( vNodes ); 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 write the AIG 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; } -#include "fra.h" - /**Function************************************************************* Synopsis [] @@ -1585,22 +914,17 @@ usage: SeeAlso [] ***********************************************************************/ -int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ) +int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) { - Abc_Ntk_t * pNtk; - char * pFileName; + Abc_Ntk_t * pNtk, * pNtkTemp; + char * FileName; int c; - int fNames; - fNames = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { - case 'n': - fNames ^= 1; - break; case 'h': goto usage; default: @@ -1615,128 +939,32 @@ int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != globalUtilOptind + 1 ) + if ( argc != util_optind + 1 ) { goto usage; } - // get the input file name - pFileName = argv[globalUtilOptind]; - if ( pNtk->pModel == NULL && pNtk->pSeqModel == NULL ) + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) { - fprintf( pAbc->Out, "Counter-example is not available.\n" ); + fprintf( stdout, "IoCommandWriteGml(): Currently can only process logic networks with BDDs.\n" ); return 0; } - // write the counter-example into the file - if ( pNtk->pModel ) - { - 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 ); - } - else - { - Fra_Cex_t * pCex = pNtk->pSeqModel; - Abc_Obj_t * pObj; - FILE * pFile; - int i, f; - Abc_NtkForEachLatch( pNtk, pObj, i ) - if ( !Abc_LatchIsInit0(pObj) ) - { - fprintf( stdout, "IoCommandWriteCounter(): The init-state should be all-0 for counter-example to work.\n" ); - fprintf( stdout, "Run commands \"undc\" and \"zero\" and then rerun the equivalence check.\n" ); - return 1; - } - - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName ); - return 1; - } - if ( fNames ) - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, "%s@0=%c ", Abc_ObjName(Abc_ObjFanout0(pObj)), '0'+!Abc_LatchIsInit0(pObj) ); - for ( f = 0; f <= pCex->iFrame; f++ ) - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, "%s@%d=%c ", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) ); - } - else - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, "%c", '0'+!Abc_LatchIsInit0(pObj) ); - for ( i = pCex->nRegs; i < pCex->nBits; i++ ) - fprintf( pFile, "%c", '0'+Abc_InfoHasBit(pCex->pData, i) ); - } - fprintf( pFile, "\n" ); - fclose( pFile ); - } - - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_counter [-nh] \n" ); - fprintf( pAbc->Err, "\t saves counter-example derived by \"sat\", \"iprove\", or \"dprove\"\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 ) + // get the input file name + FileName = argv[util_optind]; + // write the file + // get rid of complemented covers if present + if ( Abc_NtkIsSopLogic(pNtk) ) + Abc_NtkLogicMakeDirectSops(pNtk); + // derive the netlist + pNtkTemp = Abc_NtkLogicToNetlist(pNtk); + if ( pNtkTemp == NULL ) { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } + fprintf( pAbc->Out, "Writing BENCH has failed.\n" ); + return 0; } - 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 ); + Io_WriteEqn( pNtkTemp, FileName ); + Abc_NtkDelete( pNtkTemp ); return 0; usage: @@ -1760,11 +988,11 @@ usage: ***********************************************************************/ int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) { - char * pFileName; + char * FileName; int c; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1774,81 +1002,33 @@ int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) 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) ) + + if ( !Abc_NtkIsLogic(pAbc->pNtkCur) && !Abc_NtkIsStrash(pAbc->pNtkCur) ) { - fprintf( stdout, "IoCommandWriteList(): Can write adjacency list for sequential AIGs only.\n" ); + fprintf( stdout, "IoCommandWriteGml(): Currently can only process logic networks with BDDs.\n" ); return 0; } -*/ + + if ( argc != util_optind + 1 ) + { + goto usage; + } + // get the input file name - pFileName = argv[globalUtilOptind]; + FileName = argv[util_optind]; // write the file - Io_WriteList( pAbc->pNtkCur, pFileName, fUseHost ); + Io_WriteGml( pAbc->pNtkCur, FileName ); return 0; usage: - fprintf( pAbc->Err, "usage: write_list [-nh] \n" ); + fprintf( pAbc->Err, "usage: write_gml [-h] \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; @@ -1867,11 +1047,12 @@ usage: ***********************************************************************/ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) { - char * pFileName; + Abc_Ntk_t * pNtk, * pNtkTemp; + char * FileName; int c; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + util_getopt_reset(); + while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1881,111 +1062,47 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) 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 ) + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; } - 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 ); + if ( Abc_NtkGetLevelNum(pNtk) > 1 ) + { + fprintf( pAbc->Out, "PLA writing is available for collapsed networks.\n" ); + return 0; + } - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + if ( Abc_NtkLatchNum(pNtk) > 0 ) { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } + fprintf( pAbc->Out, "Latches are writed at PI/PO pairs in the PLA file.\n" ); + return 0; } - if ( argc != globalUtilOptind + 1 ) + + if ( argc != util_optind + 1 ) + { goto usage; + } // get the input file name - pFileName = argv[globalUtilOptind]; + FileName = argv[util_optind]; + // derive the netlist - pLibrary = Abc_FrameReadLibVer(); - if ( pLibrary == NULL ) + pNtkTemp = Abc_NtkLogicToNetlist(pNtk); + if ( pNtkTemp == NULL ) { - fprintf( pAbc->Out, "Verilog library is not specified.\n" ); + fprintf( pAbc->Out, "Writing PLA has failed.\n" ); return 0; } -// Io_WriteVerilogLibrary( pLibrary, pFileName ); + Io_WritePla( pNtkTemp, FileName ); + Abc_NtkDelete( pNtkTemp ); return 0; usage: - fprintf( pAbc->Err, "usage: write_verlib [-h] \n" ); - fprintf( pAbc->Err, "\t write the current verilog library\n" ); + 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; diff --git a/src/base/io/io.h b/src/base/io/io.h index 126de332..6bf3a85c 100644 --- a/src/base/io/io.h +++ b/src/base/io/io.h @@ -21,10 +21,6 @@ #ifndef __IO_H__ #define __IO_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -39,27 +35,8 @@ extern "C" { /// 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 /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// #define IO_WRITE_LINE_LENGTH 78 // the output line length @@ -68,79 +45,48 @@ typedef enum { /// 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 ===========================================================*/ +/*=== abcRead.c ==========================================================*/ +extern Abc_Ntk_t * Io_Read( 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 ===========================================================*/ +/*=== abcReadEdif.c ==========================================================*/ extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ); -/*=== abcReadEqn.c ============================================================*/ +/*=== 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 ========================================================*/ +/*=== 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, int fCompact ); -/*=== 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 ); +/*=== abcReadPla.c ==========================================================*/ +extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ); +/*=== abcUtil.c ==========================================================*/ 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 +/*=== abcWriteBlif.c ==========================================================*/ +extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); +/*=== abcWriteBench.c ==========================================================*/ +extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteCnf.c ==========================================================*/ +extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteDot.c ==========================================================*/ +extern void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName ); +/*=== abcWriteEqn.c ==========================================================*/ +extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteGml.c ==========================================================*/ +extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWritePla.c ==========================================================*/ +extern int Io_WritePla( Abc_Ntk_t * pNtk, char * FileName ); //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/base/io/ioInt.h b/src/base/io/ioInt.h index 3daf3c75..736884c4 100644 --- a/src/base/io/ioInt.h +++ b/src/base/io/ioInt.h @@ -34,16 +34,16 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/base/io/ioRead.c b/src/base/io/ioRead.c new file mode 100644 index 00000000..acf4deda --- /dev/null +++ b/src/base/io/ioRead.c @@ -0,0 +1,81 @@ +/**CFile**************************************************************** + + FileName [ioRead.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: ioRead.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Read the network from a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_Read( char * pFileName, int fCheck ) +{ + Abc_Ntk_t * pNtk, * pTemp; + // set the new network + if ( Extra_FileNameCheckExtension( pFileName, "blif" ) ) + pNtk = Io_ReadBlif( pFileName, fCheck ); + else if ( Extra_FileNameCheckExtension( pFileName, "v" ) ) + pNtk = Io_ReadVerilog( pFileName, fCheck ); + else if ( Extra_FileNameCheckExtension( pFileName, "bench" ) ) + pNtk = Io_ReadBench( pFileName, fCheck ); + else if ( Extra_FileNameCheckExtension( pFileName, "edf" ) ) + pNtk = Io_ReadEdif( pFileName, fCheck ); + else if ( Extra_FileNameCheckExtension( pFileName, "pla" ) ) + pNtk = Io_ReadPla( pFileName, fCheck ); + else if ( Extra_FileNameCheckExtension( pFileName, "eqn" ) ) + pNtk = Io_ReadEqn( pFileName, fCheck ); + else + { + fprintf( stderr, "Unknown file format\n" ); + return NULL; + } + if ( pNtk == NULL ) + return NULL; + + pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting to logic network after reading has failed.\n" ); + return NULL; + } + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c deleted file mode 100644 index 4820bced..00000000 --- a/src/base/io/ioReadAiger.c +++ /dev/null @@ -1,366 +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 /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**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)); -} - -/**Function************************************************************* - - Synopsis [Decodes the encoded array of literals.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Io_WriteDecodeLiterals( char ** ppPos, int nEntries ) -{ - Vec_Int_t * vLits; - int Lit, LitPrev, Diff, i; - vLits = Vec_IntAlloc( nEntries ); - LitPrev = Io_ReadAigerDecode( ppPos ); - Vec_IntPush( vLits, LitPrev ); - for ( i = 1; i < nEntries; i++ ) - { -// Diff = Lit - LitPrev; -// Diff = (Lit < LitPrev)? -Diff : Diff; -// Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev); - Diff = Io_ReadAigerDecode( ppPos ); - Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1; - Lit = Diff + LitPrev; - Vec_IntPush( vLits, Lit ); - LitPrev = Lit; - } - return vLits; -} - -/**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; - Vec_Int_t * vLits = NULL; - 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 || (pContents[3] != ' ' && pContents[3] != '2') ) - { - 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 ); - } - - - if ( pContents[3] == ' ' ) // standard AIGER - { - // 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++; - } - else // modified AIGER - { - vLits = Io_WriteDecodeLiterals( &pCur, nLatches + nOutputs ); - } - - // 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; - if ( pContents[3] == ' ' ) // standard AIGER - { - 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 ); - } - // 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 ); - } - } - else - { - // read the latch driver literals - Abc_NtkForEachLatchInput( pNtkNew, pObj, i ) - { - uLit0 = Vec_IntEntry( vLits, i ); - pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); - Abc_ObjAddFanin( pObj, pNode0 ); - } - // read the PO driver literals - Abc_NtkForEachPo( pNtkNew, pObj, i ) - { - uLit0 = Vec_IntEntry( vLits, i+Abc_NtkLatchNum(pNtkNew) ); - pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); - Abc_ObjAddFanin( pObj, pNode0 ); - } - Vec_IntFree( vLits ); - } - - // 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; -} - - - -//////////////////////////////////////////////////////////////////////// -/// 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 index 007147bc..393b2216 100644 --- a/src/base/io/ioReadBench.c +++ b/src/base/io/ioReadBench.c @@ -27,7 +27,7 @@ static Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -47,7 +47,7 @@ Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ) Abc_Ntk_t * pNtk; // start the file - p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t,()=" ); + p = Extra_FileReaderAlloc( pFileName, "#", "\n", " \t\r,()=" ); if ( p == NULL ) return NULL; @@ -66,7 +66,6 @@ Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ) } return pNtk; } - /**Function************************************************************* Synopsis [] @@ -83,11 +82,10 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) ProgressBar * pProgress; Vec_Ptr_t * vTokens; Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode, * pNet; + Abc_Obj_t * pNet, * pNode; Vec_Str_t * vString; - unsigned uTruth[8]; - char * pType, ** ppNames, * pString; - int iLine, nNames, nDigits, fLutsPresent = 0; + char * pType, ** ppNames; + int iLine, nNames; // allocate the empty network pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); @@ -102,7 +100,6 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) if ( vTokens->nSize == 1 ) { printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); - Vec_StrFree( vString ); Abc_NtkDelete( pNtk ); return NULL; } @@ -116,90 +113,8 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) { // 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; - } - } - } + if ( strcmp(pType, "DFF") == 0 ) + Io_ReadCreateLatch( pNtk, vTokens->pArray[2], vTokens->pArray[0] ); else { // create a new node and add it to the network @@ -208,7 +123,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) 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) ); + Abc_ObjSetData( pNode, Abc_SopCreateAnd(pNtk->pManFunc, nNames) ); else if ( strcmp(pType, "OR") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateOr(pNtk->pManFunc, nNames, NULL) ); else if ( strcmp(pType, "NAND") == 0 ) @@ -217,22 +132,15 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) 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 ) + else if ( strcmp(pType, "NXOR") == 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 + else { - printf( "Io_ReadBenchNetwork(): Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) ); - Vec_StrFree( vString ); + printf( "Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) ); Abc_NtkDelete( pNtk ); return NULL; } @@ -242,116 +150,17 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) 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 ); - } - } + // check if constant 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 ); - - // 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 index d0750178..946de42b 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -33,47 +33,42 @@ struct Io_ReadBlif_t_ 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 + Abc_Ntk_t * pNtk; // the primary network + Abc_Ntk_t * pNtkExdc; // the exdc network + int fParsingExdc; // this flag is on, when we are parsing EXDC 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 Abc_Ntk_t * Io_ReadBlifNetwork( 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Reads the (hierarchical) network from the BLIF file.] + Synopsis [Reads the network from a BLIF file.] - Description [] + Description [Works only for flat (non-hierarchical) BLIF.] SideEffects [] @@ -83,22 +78,34 @@ static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMa Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) { Io_ReadBlif_t * p; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkExdc; // start the file p = Io_ReadBlifFile( pFileName ); if ( p == NULL ) return NULL; - // read the hierarchical network + // read the network pNtk = Io_ReadBlifNetwork( p ); if ( pNtk == NULL ) { Io_ReadBlifFree( p ); return NULL; } - pNtk->pSpec = Extra_UtilStrsav( pFileName ); Abc_NtkTimeInitialize( pNtk ); + + // read the EXDC network + if ( p->fParsingExdc ) + { + pNtkExdc = Io_ReadBlifNetwork( p ); + if ( pNtkExdc == NULL ) + { + Abc_NtkDelete( pNtk ); + Io_ReadBlifFree( p ); + return NULL; + } + pNtk->pExdc = pNtkExdc; + } Io_ReadBlifFree( p ); // make sure that everything is okay with the network structure @@ -113,7 +120,7 @@ Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) /**Function************************************************************* - Synopsis [Iteratively reads several networks in the hierarchical design.] + Synopsis [Starts the reading data structure.] Description [] @@ -122,80 +129,140 @@ Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) +Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) { - Abc_Ntk_t * pNtk, * pNtkMaster; + Extra_FileReader_t * pReader; + Io_ReadBlif_t * p; - // 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 ); + // start the reader + pReader = Extra_FileReaderAlloc( pFileName, "#", "\n", " \t\r" ); + if ( pReader == NULL ) return NULL; - } - // read networks (with EXDC) - pNtkMaster = NULL; - while ( p->vTokens ) + // 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 [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) +{ + 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 ) { - // 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 ); -*/ + for ( i = 0; i < p->vNewTokens->nSize; i++ ) + free( p->vNewTokens->pArray[i] ); + p->vNewTokens->nSize = 0; } -/* - // if there is a hierarchy, connect the boxes - if ( pNtkMaster && pNtkMaster->tName2Model ) + + // 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, util_strsav(vTokens->pArray[i]) ); + + // load as long as there is the line break + while ( 1 ) { - if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) ) + // 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 ] == '\\' ) { - Abc_NtkDelete( pNtkMaster ); - return NULL; + // 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, util_strsav(vTokens->pArray[i]) ); + continue; } + // otherwise, load them and break + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) ); + break; } - else -*/ - if ( !p->fError ) - Abc_NtkFinalizeRead( pNtkMaster ); - // return the master network - return pNtkMaster; + return p->vNewTokens; } + /**Function************************************************************* - Synopsis [Reads one (main or exdc) network from the BLIF file.] + Synopsis [Reads the BLIF file.] Description [] @@ -204,89 +271,74 @@ Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) +Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) { ProgressBar * pProgress; - Abc_Ntk_t * pNtk; - char * pDirective; + Vec_Ptr_t * vTokens; + char * pModelName, * 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 ) + if ( !p->fParsingExdc ) { - 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 model name + vTokens = Io_ReadBlifGetTokens(p); + if ( vTokens == NULL || strcmp( vTokens->pArray[0], ".model" ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Wrong input file format." ); + Io_ReadBlifPrintErrorMessage( p ); + return NULL; + } + pModelName = vTokens->pArray[1]; + // allocate the empty network + p->pNtk = Abc_NtkAlloc( ABC_TYPE_NETLIST, ABC_FUNC_SOP ); + p->pNtk->pName = util_strsav( pModelName ); + p->pNtk->pSpec = util_strsav( p->pFileName ); } + else + p->pNtk = Abc_NtkAlloc( ABC_TYPE_NETLIST, ABC_FUNC_SOP ); // 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++ ) + for ( iLine = 0; fTokensReady || (vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) { - if ( p->pNtkMaster == NULL && iLine % 1000 == 0 ) + if ( iLine % 1000 == 0 ) Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); // consider different line types fTokensReady = 0; - pDirective = p->vTokens->pArray[0]; + pDirective = vTokens->pArray[0]; if ( !strcmp( pDirective, ".names" ) ) - { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; } + { fStatus = Io_ReadBlifNetworkNames( p, &vTokens ); fTokensReady = 1; } else if ( !strcmp( pDirective, ".gate" ) ) - fStatus = Io_ReadBlifNetworkGate( p, p->vTokens ); + fStatus = Io_ReadBlifNetworkGate( p, vTokens ); else if ( !strcmp( pDirective, ".latch" ) ) - fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens ); + fStatus = Io_ReadBlifNetworkLatch( p, vTokens ); else if ( !strcmp( pDirective, ".inputs" ) ) - fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens ); + fStatus = Io_ReadBlifNetworkInputs( p, vTokens ); else if ( !strcmp( pDirective, ".outputs" ) ) - fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens ); - else if ( !strcmp( pDirective, ".asserts" ) ) - fStatus = Io_ReadBlifNetworkAsserts( p, p->vTokens ); + fStatus = Io_ReadBlifNetworkOutputs( p, vTokens ); else if ( !strcmp( pDirective, ".input_arrival" ) ) - fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens ); + fStatus = Io_ReadBlifNetworkInputArrival( 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 ); + fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, vTokens ); else if ( !strcmp( pDirective, ".exdc" ) ) - break; + { p->fParsingExdc = 1; 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 + if ( 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; + Abc_NtkFinalizeRead( p->pNtk ); + return p->pNtk; } /**Function************************************************************* @@ -304,7 +356,7 @@ 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] ); + Io_ReadCreatePi( p->pNtk, vTokens->pArray[i] ); return 0; } @@ -323,26 +375,7 @@ 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] ); + Io_ReadCreatePo( p->pNtk, vTokens->pArray[i] ); return 0; } @@ -358,10 +391,11 @@ int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) ***********************************************************************/ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - Abc_Ntk_t * pNtk = p->pNtkCur; +{ + Abc_Ntk_t * pNtk = p->pNtk; Abc_Obj_t * pLatch; int ResetValue; + if ( vTokens->nSize < 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); @@ -373,10 +407,10 @@ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) pLatch = Io_ReadCreateLatch( pNtk, vTokens->pArray[1], vTokens->pArray[2] ); // get the latch reset value if ( vTokens->nSize == 3 ) - Abc_LatchSetInitDc( pLatch ); + ResetValue = 2; else { - ResetValue = atoi(vTokens->pArray[vTokens->nSize-1]); + ResetValue = atoi(vTokens->pArray[3]); if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); @@ -384,13 +418,8 @@ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) 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 ); } + Abc_ObjSetData( pLatch, (void *)ResetValue ); return 0; } @@ -408,7 +437,7 @@ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) { Vec_Ptr_t * vTokens = *pvTokens; - Abc_Ntk_t * pNtk = p->pNtkCur; + Abc_Ntk_t * pNtk = p->pNtk; Abc_Obj_t * pNode; char * pToken, Char, ** ppNames; int nFanins, nNames; @@ -471,7 +500,7 @@ int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) 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' ) + if ( Char != '0' && Char != '1' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The output character in the constant cube is wrong." ); @@ -496,16 +525,6 @@ int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) // 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; @@ -531,7 +550,7 @@ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) int i, nNames; // check that the library is available - pGenlib = Abc_FrameReadLibGen(); + pGenlib = Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()); if ( pGenlib == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); @@ -560,12 +579,12 @@ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) } // if this is the first line with gate, update the network type - if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) + if ( Abc_NtkNodeNum(p->pNtk) == 0 ) { - assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); - p->pNtkCur->ntkFunc = ABC_FUNC_MAP; - Extra_MmFlexStop( p->pNtkCur->pManFunc ); - p->pNtkCur->pManFunc = pGenlib; + assert( p->pNtk->ntkFunc == ABC_FUNC_SOP ); + p->pNtk->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( p->pNtk->pManFunc, 0 ); + p->pNtk->pManFunc = pGenlib; } // remove the formal parameter names @@ -584,54 +603,13 @@ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) // create the node ppNames = (char **)vTokens->pArray + 2; nNames = vTokens->nSize - 3; - pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); + pNode = Io_ReadCreateNode( p->pNtk, 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************************************************************* @@ -680,7 +658,7 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) Io_ReadBlifPrintErrorMessage( p ); return 1; } - pNet = Abc_NtkFindNet( p->pNtkCur, vTokens->pArray[1] ); + pNet = Abc_NtkFindNet( p->pNtk, vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); @@ -698,7 +676,7 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) return 1; } // set the arrival time - Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); + Abc_NtkTimeSetArrival( p->pNtk, pNet->Id, (float)TimeRise, (float)TimeFall ); return 0; } @@ -737,366 +715,10 @@ int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vToken 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; + Abc_NtkTimeSetDefaultArrival( p->pNtk, (float)TimeRise, (float)TimeFall ); 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 97f2fbf3..00000000 --- a/src/base/io/ioReadBlifMv.c +++ /dev/null @@ -1,1702 +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 ); - Io_MvFree( p ); - if ( pDesign == NULL ) - return NULL; -// 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 if ( !strncmp(pCur, "delay", 5) ) - {} - else if ( !strncmp(pCur, "input_arrival", 13) ) - {} - else if ( !strncmp(pCur, "output_required", 15) ) - {} - 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_PtrEntryLast(vTokens) ); - 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 index 188e5b8c..48a1722b 100644 --- a/src/base/io/ioReadEdif.c +++ b/src/base/io/ioReadEdif.c @@ -27,7 +27,7 @@ static Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -46,11 +46,8 @@ 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()" ); + p = Extra_FileReaderAlloc( pFileName, "#", "\n", " \t\r()" ); if ( p == NULL ) return NULL; @@ -117,15 +114,11 @@ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * 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!!! + pObj->pData = Abc_NtkRegisterName( pNtk, pGateName ); } Abc_ObjAddFanin( pNet, pObj ); } @@ -185,7 +178,7 @@ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) else if ( strcmp( vTokens->pArray[0], "design" ) == 0 ) { free( pNtk->pName ); - pNtk->pName = Extra_UtilStrsav( vTokens->pArray[3] ); + pNtk->pName = util_strsav( vTokens->pArray[3] ); break; } } @@ -195,7 +188,7 @@ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) Abc_NtkForEachNode( pNtk, pObj, i ) { if ( strncmp( pObj->pData, "And", 3 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateAnd(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); + Abc_ObjSetData( pObj, Abc_SopCreateAnd(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); 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 ) diff --git a/src/base/io/ioReadEqn.c b/src/base/io/ioReadEqn.c index e04f2b1a..20d30a1a 100644 --- a/src/base/io/ioReadEqn.c +++ b/src/base/io/ioReadEqn.c @@ -30,7 +30,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -85,20 +85,19 @@ Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) { ProgressBar * pProgress; Vec_Ptr_t * vTokens; - Vec_Ptr_t * vVars; + Vec_Ptr_t * vCubes, * vLits, * vVars; Abc_Ntk_t * pNtk; Abc_Obj_t * pNode; - char * pNodeName, * pFormula, * pFormulaCopy, * pVarName; - int iLine, i; + char * pCubesCopy, * pSopCube, * pVarName; + int iLine, iNum, i, k; // 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)); + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); // go through the lines of the file + vCubes = Vec_PtrAlloc( 100 ); vVars = Vec_PtrAlloc( 100 ); + vLits = Vec_PtrAlloc( 100 ); pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) { @@ -132,36 +131,52 @@ Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) } 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 ); - + // remove spaces + pCubesCopy = vTokens->pArray[1]; + Io_ReadEqnStrCompact( pCubesCopy ); // consider the case of the constant node - if ( pFormula[1] == 0 && (pFormula[0] == '0' || pFormula[0] == '1') ) + if ( (pCubesCopy[0] == '0' || pCubesCopy[0] == '1') && pCubesCopy[1] == 0 ) { - pFormulaCopy = NULL; - Vec_PtrClear( vVars ); + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], NULL, 0 ); + if ( pCubesCopy[0] == '0' ) + pNode->pData = Abc_SopCreateConst0( pNtk->pManFunc ); + else + pNode->pData = Abc_SopCreateConst1( pNtk->pManFunc ); + continue; } - else + // determine unique variables + pCubesCopy = util_strsav( pCubesCopy ); + // find the names of the fanins of this node + Io_ReadEqnStrCutAt( pCubesCopy, "!*+", 1, vVars ); + // create the node + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], (char **)vVars->pArray, vVars->nSize ); + // split the string into cubes + Io_ReadEqnStrCutAt( vTokens->pArray[1], "+", 0, vCubes ); + // start the sop + pNode->pData = Abc_SopStart( pNtk->pManFunc, vCubes->nSize, vVars->nSize ); + // read the cubes + i = 0; + Abc_SopForEachCube( pNode->pData, vVars->nSize, pSopCube ) { - // 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 ); + // split this cube into lits + Io_ReadEqnStrCutAt( vCubes->pArray[i], "*", 0, vLits ); + // read the literals + Vec_PtrForEachEntry( vLits, pVarName, k ) + { + iNum = Io_ReadEqnStrFind( vVars, pVarName + (pVarName[0] == '!') ); + assert( iNum >= 0 ); + pSopCube[iNum] = '1' - (pVarName[0] == '!'); + } + i++; } - // 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 ); + assert( i == vCubes->nSize ); // remove the cubes - FREE( pFormulaCopy ); + free( pCubesCopy ); } } Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vCubes ); + Vec_PtrFree( vLits ); Vec_PtrFree( vVars ); Abc_NtkFinalizeRead( pNtk ); return pNtk; diff --git a/src/base/io/ioReadPla.c b/src/base/io/ioReadPla.c index fdfdb4f6..1e54db5f 100644 --- a/src/base/io/ioReadPla.c +++ b/src/base/io/ioReadPla.c @@ -27,7 +27,7 @@ static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -47,7 +47,7 @@ Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ) Abc_Ntk_t * pNtk; // start the file - p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t|" ); + p = Extra_FileReaderAlloc( pFileName, "#", "\n", " \t\r|" ); if ( p == NULL ) return NULL; @@ -131,7 +131,7 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ) for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePo( pNtk, vTokens->pArray[i] ); } - else + else { // check if the input/output names are given if ( Abc_NtkPiNum(pNtk) == 0 ) @@ -229,7 +229,6 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ) { Abc_ObjRemoveFanins(pNode); pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" ); - Vec_StrFree( ppSops[i] ); continue; } Vec_StrPush( ppSops[i], 0 ); diff --git a/src/base/io/ioReadVerilog.c b/src/base/io/ioReadVerilog.c index c64e330c..f4855dde 100644 --- a/src/base/io/ioReadVerilog.c +++ b/src/base/io/ioReadVerilog.c @@ -6,7 +6,7 @@ PackageName [Command processing package.] - Synopsis [Procedure to read network from file.] + Synopsis [Procedures to read a subset of structural Verilog from IWLS 2005 benchmark.] Author [Alan Mishchenko] @@ -24,17 +24,109 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); +typedef struct Io_ReadVer_t_ Io_ReadVer_t; // all reading info +struct Io_ReadVer_t_ +{ + // general info about file + char * pFileName; // the name of the file + Extra_FileReader_t* pReader; // the input file reader + // current processing info + st_table * tKeywords; // mapping of keywords into codes + Abc_Ntk_t * pNtk; // the primary network + // the error message + FILE * Output; // the output stream + char sError[1000]; // the error string generated during parsing + int LineCur; // the line currently being parsed + Vec_Ptr_t * vSkipped; // temporary storage for skipped objects +}; + +// verilog keyword types +typedef enum { + VER_NONE = 0, + VER_MODULE = -1, + VER_ENDMODULE = -2, + VER_INPUT = -3, + VER_OUTPUT = -4, + VER_INOUT = -5, + VER_WIRE = -6, + VER_ASSIGN = -7 +} Ver_KeywordType_t; + +// the list of verilog keywords +static char * s_Keywords[10] = +{ + NULL, // unused + "module", // -1 + "endmodule", // -2 + "input", // -3 + "output", // -4 + "inout", // -5 + "wire", // -6 + "assign" // -7 +}; + +// the list of gates in the Cadence library +static char * s_CadenceGates[40][5] = +{ + { "INVX1", "1", "1", "0 1\n", NULL }, // 0 + { "INVX2", "1", "1", "0 1\n", NULL }, // 1 + { "INVX4", "1", "1", "0 1\n", NULL }, // 2 + { "INVX8", "1", "1", "0 1\n", NULL }, // 3 + { "BUFX1", "1", "1", "1 1\n", NULL }, // 4 + { "BUFX3", "1", "1", "1 1\n", NULL }, // 5 + { "NOR2X1", "2", "1", "00 1\n", NULL }, // 6 + { "NOR3X1", "3", "1", "000 1\n", NULL }, // 7 + { "NOR4X1", "4", "1", "0000 1\n", NULL }, // 8 + { "NAND2X1", "2", "1", "11 0\n", NULL }, // 9 + { "NAND2X2", "2", "1", "11 0\n", NULL }, // 10 + { "NAND3X1", "3", "1", "111 0\n", NULL }, // 11 + { "NAND4X1", "4", "1", "1111 0\n", NULL }, // 12 + { "OR2X1", "2", "1", "00 0\n", NULL }, // 13 + { "OR4X1", "4", "1", "0000 0\n", NULL }, // 14 + { "AND2X1", "2", "1", "11 1\n", NULL }, // 15 + { "XOR2X1", "2", "1", "01 1\n10 1\n", NULL }, // 16 + { "MX2X1", "3", "1", "01- 1\n1-1 1\n", NULL }, // 17 + { "OAI21X1", "3", "1", "00- 1\n--0 1\n", NULL }, // 18 + { "OAI22X1", "4", "1", "00-- 1\n--00 1\n", NULL }, // 19 + { "OAI33X1", "6", "1", "000--- 1\n---000 1\n", NULL }, // 20 + { "AOI21X1", "3", "1", "11- 0\n--1 0\n", NULL }, // 21 + { "AOI22X1", "4", "1", "11-- 0\n--11 0\n", NULL }, // 22 + { "CLKBUFX1", "1", "1", "1 1\n", NULL }, // 23 + { "CLKBUFX2", "1", "1", "1 1\n", NULL }, // 24 + { "CLKBUFX3", "1", "1", "1 1\n", NULL }, // 25 + { "ADDHX1", "2", "2", "11 1\n", "01 1\n10 1\n" }, // 26 + { "ADDFX1", "3", "2", "11- 1\n-11 1\n1-1 1\n", "001 1\n010 1\n100 1\n111 1\n" }, // 27 + { "DFFSRX1", "1", "1", NULL, NULL }, // 28 + { "DFFX1", "1", "1", NULL, NULL }, // 29 + { "SDFFSRX1", "1", "1", NULL, NULL }, // 30 + { "TLATSRX1", "1", "1", NULL, NULL }, // 31 + { "TLATX1", "1", "1", NULL, NULL }, // 32 + { "TBUFX1", "1", "1", NULL, NULL }, // 33 + { "TBUFX2", "1", "1", NULL, NULL }, // 34 + { "TBUFX4", "1", "1", NULL, NULL }, // 35 + { "TBUFX8", "1", "1", NULL, NULL }, // 36 + { "TINVX1", "1", "1", NULL, NULL } // 37 +}; + +static Io_ReadVer_t * Io_ReadVerFile( char * pFileName ); +static Abc_Ntk_t * Io_ReadVerNetwork( Io_ReadVer_t * p ); +static bool Io_ReadVerNetworkAssign( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens ); +static bool Io_ReadVerNetworkSignal( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType ); +static bool Io_ReadVerNetworkGateSimple( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType ); +static bool Io_ReadVerNetworkGateComplex( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType ); +static bool Io_ReadVerNetworkLatch( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens ); +static void Io_ReadVerPrintErrorMessage( Io_ReadVer_t * p ); +static void Io_ReadVerFree( Io_ReadVer_t * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Reads hierarchical design from the Verilog file.] + Synopsis [Reads the network from a Verilog file.] - Description [] + Description [Works only for IWLS 2005 benchmarks.] SideEffects [] @@ -43,45 +135,620 @@ extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fC ***********************************************************************/ Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ) { + Io_ReadVer_t * p; Abc_Ntk_t * pNtk; - Abc_Lib_t * pDesign; - int RetValue; - // parse the verilog file - pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 ); - if ( pDesign == NULL ) + // start the file + p = Io_ReadVerFile( pFileName ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadVerNetwork( p ); + Io_ReadVerFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadVerilog: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Starts the reading data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_ReadVer_t * Io_ReadVerFile( char * pFileName ) +{ + Extra_FileReader_t * pReader; + Io_ReadVer_t * p; + int i; + + // start the reader + pReader = Extra_FileReaderAlloc( pFileName, "/", ";", " \t\r\n,()" ); + if ( pReader == 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 ); + // start the reading data structure + p = ALLOC( Io_ReadVer_t, 1 ); + memset( p, 0, sizeof(Io_ReadVer_t) ); + p->pFileName = pFileName; + p->pReader = pReader; + p->Output = stdout; + p->vSkipped = Vec_PtrAlloc( 100 ); + + // insert the keywords and gate names into the hash table + p->tKeywords = st_init_table(strcmp, st_strhash); + for ( i = 0; i < 10; i++ ) + if ( s_Keywords[i] ) + st_insert( p->tKeywords, (char *)s_Keywords[i], (char *)-i ); + for ( i = 0; i < 40; i++ ) + if ( s_CadenceGates[i][0] ) + st_insert( p->tKeywords, (char *)s_CadenceGates[i][0], (char *)i ); + return p; +} - // extract the master network - pNtk->pDesign = pDesign; - pDesign->pManFunc = NULL; +/**Function************************************************************* + + Synopsis [Frees the data structure.] + + Description [] + + SideEffects [] - // verify the design for cyclic dependence - assert( Vec_PtrSize(pDesign->vModules) > 0 ); - if ( Vec_PtrSize(pDesign->vModules) == 1 ) + SeeAlso [] + +***********************************************************************/ +void Io_ReadVerFree( Io_ReadVer_t * p ) +{ + Extra_FileReaderFree( p->pReader ); + Vec_PtrFree( p->vSkipped ); + st_free_table( p->tKeywords ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadVerPrintErrorMessage( Io_ReadVer_t * p ) +{ + 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 [Reads the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadVerNetwork( Io_ReadVer_t * p ) +{ + char Buffer[1000]; + ProgressBar * pProgress; + Ver_KeywordType_t LineType; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + char * pModelName; + int i; + + // read the model name + vTokens = Extra_FileReaderGetTokens( p->pReader ); + if ( vTokens == NULL || strcmp( vTokens->pArray[0], "module" ) ) { -// printf( "Warning: The design is not hierarchical.\n" ); - Abc_LibFree( pDesign, pNtk ); - pNtk->pDesign = NULL; - pNtk->pSpec = Extra_UtilStrsav( pFileName ); + p->LineCur = 0; + sprintf( p->sError, "Wrong input file format." ); + Io_ReadVerPrintErrorMessage( p ); + return NULL; } - else + pModelName = vTokens->pArray[1]; + + // allocate the empty network + pNtk = Abc_NtkAlloc( ABC_TYPE_NETLIST, ABC_FUNC_SOP ); + pNtk->pName = util_strsav( pModelName ); + pNtk->pSpec = util_strsav( p->pFileName ); + + // create constant nodes and nets + Abc_NtkFindOrCreateNet( pNtk, "1'b0" ); + Abc_NtkFindOrCreateNet( pNtk, "1'b1" ); + Io_ReadCreateConst( pNtk, "1'b0", 0 ); + Io_ReadCreateConst( pNtk, "1'b1", 1 ); + + // read the inputs/outputs + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); + for ( i = 0; vTokens = Extra_FileReaderGetTokens(p->pReader); i++ ) { - // check that there is no cyclic dependency - Abc_NtkIsAcyclicHierarchy( pNtk ); + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); + + // get the line type + if ( !st_lookup( p->tKeywords, vTokens->pArray[0], (char **)&LineType ) ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "The first token \"%s\" cannot be recognized.", vTokens->pArray[0] ); + Io_ReadVerPrintErrorMessage( p ); + return NULL; + } + // consider Verilog directives + if ( LineType < 0 ) + { + if ( LineType == VER_ENDMODULE ) + break; + if ( LineType == VER_ASSIGN ) + { + if ( !Io_ReadVerNetworkAssign( p, pNtk, vTokens ) ) + return NULL; + continue; + } + if ( !Io_ReadVerNetworkSignal( p, pNtk, vTokens, LineType ) ) + return NULL; + continue; + } + // proces single output gates + if ( LineType < 26 ) + { + if ( !Io_ReadVerNetworkGateSimple( p, pNtk, vTokens, LineType ) ) + return NULL; + continue; + } + // process complex gates + if ( LineType < 28 ) + { + if ( !Io_ReadVerNetworkGateComplex( p, pNtk, vTokens, LineType ) ) + return NULL; + continue; + + } + // process the latches + if ( LineType < 33 ) + { + if ( !Io_ReadVerNetworkLatch( p, pNtk, vTokens ) ) + return NULL; + continue; + } + // add the tri-state element to the skipped ones + sprintf( Buffer, "%s %s", vTokens->pArray[0], vTokens->pArray[1] ); + Vec_PtrPush( p->vSkipped, util_strsav(Buffer) ); } + Extra_ProgressBarStop( pProgress ); -//Io_WriteVerilog( pNtk, "_temp.v" ); + if ( p->vSkipped->nSize > 0 ) + { + printf( "IoReadVerilog() skipped %d tri-state elements:\n", p->vSkipped->nSize ); + for ( i = 0; i < p->vSkipped->nSize; i++ ) + { + if ( i < 2 ) + printf( "%s,\n", p->vSkipped->pArray[i] ); + else + { + printf( "%s, etc.\n", p->vSkipped->pArray[i] ); + break; + } + } + for ( i = 0; i < p->vSkipped->nSize; i++ ) + free( p->vSkipped->pArray[i] ); + } + Abc_NtkFinalizeRead( pNtk ); return pNtk; } +/**Function************************************************************* + + Synopsis [Reads one assign directive in the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Io_ReadVerNetworkAssign( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens ) +{ + assert( strcmp( vTokens->pArray[0], "assign" ) == 0 ); + // make sure the driving variable exists + if ( !Abc_NtkFindNet( pNtk, vTokens->pArray[3] ) ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find net \"%s\". The assign operator is handled only for assignment to a variable and a constant.", vTokens->pArray[3] ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + // make sure the driven variable exists + if ( !Abc_NtkFindNet( pNtk, vTokens->pArray[1] ) ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find net \"%s\".", vTokens->pArray[1] ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + // create a buffer + Io_ReadCreateBuf( pNtk, vTokens->pArray[3], vTokens->pArray[1] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Reads one signal the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Io_ReadVerNetworkSignal( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType ) +{ + Abc_Obj_t * pNet; + char Buffer[1000]; + char * pToken; + int nSignals, k, Start, s; + + nSignals = 0; + pToken = vTokens->pArray[1]; + if ( pToken[0] == '[' ) + { + nSignals = atoi(pToken + 1) + 1; + if ( nSignals < 1 || nSignals > 1024 ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Incorrect number of signals in the expression \"%s\".", pToken ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + if ( nSignals == 1 ) + nSignals = 0; + Start = 2; + } + else + Start = 1; + for ( k = Start; k < vTokens->nSize; k++ ) + { + pToken = vTokens->pArray[k]; + // print the signal name + if ( nSignals ) + { + for ( s = 0; s < nSignals; s++ ) + { + sprintf( Buffer, "%s[%d]", pToken, s ); + if ( LineType == VER_INPUT || LineType == VER_INOUT ) + Io_ReadCreatePi( pNtk, Buffer ); + if ( LineType == VER_OUTPUT || LineType == VER_INOUT ) + Io_ReadCreatePo( pNtk, Buffer ); + if ( LineType != VER_INPUT && LineType != VER_OUTPUT && LineType != VER_INOUT ) + pNet = Abc_NtkFindOrCreateNet( pNtk, Buffer ); + } + } + else + { + if ( LineType == VER_INPUT || LineType == VER_INOUT ) + Io_ReadCreatePi( pNtk, pToken ); + if ( LineType == VER_OUTPUT || LineType == VER_INOUT ) + Io_ReadCreatePo( pNtk, pToken ); + if ( LineType != VER_INPUT && LineType != VER_OUTPUT && LineType != VER_INOUT ) + pNet = Abc_NtkFindOrCreateNet( pNtk, pToken ); + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Reads a simple gate from the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Io_ReadVerNetworkGateSimple( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType ) +{ + Abc_Obj_t * pNet, * pNode; + char * pToken; + int nFanins, k; + + // create the node + pNode = Abc_NtkCreateNode( pNtk ); + // add the fanin nets + nFanins = s_CadenceGates[LineType][1][0] - '0'; + // skip the gate type and gate name + for ( k = 2; k < vTokens->nSize - 1; k++ ) + { + pToken = vTokens->pArray[k]; + if ( pToken[0] == '.' ) + continue; + pNet = Abc_NtkFindNet( pNtk, pToken ); + if ( pNet ) + { + Abc_ObjAddFanin( pNode, pNet ); + continue; + } + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find net \"%s\".", pToken ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + if ( Abc_ObjFaninNum(pNode) != nFanins ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Gate \"%s\" has a wrong number of inputs.", vTokens->pArray[1] ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + + // add the fanout net + pToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pToken[0] == '.' ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Gate \"%s\" does not have a fanout.", vTokens->pArray[1] ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + pNet = Abc_NtkFindNet( pNtk, pToken ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find net \"%s\".", pToken ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + Abc_ObjAddFanin( pNet, pNode ); + // set the function + Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, s_CadenceGates[LineType][3]) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Reads a complex gate from the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Io_ReadVerNetworkGateComplex( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNet; + char * pToken, * pToken1, * pToken2; + int nFanins, k; + + // create the nodes + pNode1 = Abc_NtkCreateNode( pNtk ); + pNode2 = Abc_NtkCreateNode( pNtk ); + // skip the gate type and gate name + // add the fanin nets + nFanins = s_CadenceGates[LineType][1][0] - '0'; + for ( k = 2; k < vTokens->nSize; k++ ) + { + pToken = vTokens->pArray[k]; + if ( pToken[0] == '.' ) + continue; + pNet = Abc_NtkFindNet( pNtk, pToken ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find net \"%s\".", pToken ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + Abc_ObjAddFanin( pNode1, pNet ); + Abc_ObjAddFanin( pNode2, pNet ); + if ( Abc_ObjFaninNum(pNode1) == nFanins ) + { + k++; + break; + } + } + // find the tokens corresponding to the output + pToken1 = pToken2 = NULL; + for ( ; k < vTokens->nSize; k++ ) + { + pToken = vTokens->pArray[k]; + if ( pToken[0] == '.' ) + continue; + if ( pToken1 == NULL ) + pToken1 = pToken; + else + pToken2 = pToken; + } + // quit if one of the tokens is not given + if ( pToken1 == NULL || pToken2 == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "An output of a two-output gate \"%s\" is not specified.", vTokens->pArray[1] ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + + // add the fanout net + pNet = Abc_NtkFindNet( pNtk, pToken1 ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find net \"%s\".", pToken1 ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + Abc_ObjAddFanin( pNet, pNode1 ); + + // add the fanout net + pNet = Abc_NtkFindNet( pNtk, pToken2 ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find net \"%s\".", pToken2 ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + Abc_ObjAddFanin( pNet, pNode2 ); + Abc_ObjSetData( pNode1, Abc_SopRegister(pNtk->pManFunc, s_CadenceGates[LineType][3]) ); + Abc_ObjSetData( pNode2, Abc_SopRegister(pNtk->pManFunc, s_CadenceGates[LineType][4]) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Reads a latch from the verilog file.] + + Description [This procedure treats T-latch as if it were D-latch.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Io_ReadVerNetworkLatch( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens ) +{ + Abc_Obj_t * pLatch, * pNet; + char * pLatchName; + char * pToken, * pToken2, * pTokenRN, * pTokenSN, * pTokenSI, * pTokenSE, * pTokenD, * pTokenQ, * pTokenQN; + int k, fRN1, fSN1; + + // get the latch name + pLatchName = vTokens->pArray[1]; + + // collect the FF signals + pTokenRN = pTokenSN = pTokenSI = pTokenSE = pTokenD = pTokenQ = pTokenQN = NULL; + for ( k = 2; k < vTokens->nSize-1; k++ ) + { + pToken = vTokens->pArray[k]; + pToken2 = vTokens->pArray[k+1]; + if ( pToken[1] == 'R' && pToken[2] == 'N' && pToken[3] == 0 ) + pTokenRN = (pToken2[0] == '.')? NULL : pToken2; + else if ( pToken[1] == 'S' && pToken[2] == 'N' && pToken[3] == 0 ) + pTokenSN = (pToken2[0] == '.')? NULL : pToken2; + else if ( pToken[1] == 'S' && pToken[2] == 'I' && pToken[3] == 0 ) + pTokenSI = (pToken2[0] == '.')? NULL : pToken2; + else if ( pToken[1] == 'S' && pToken[2] == 'E' && pToken[3] == 0 ) + pTokenSE = (pToken2[0] == '.')? NULL : pToken2; + else if ( pToken[1] == 'D' && pToken[2] == 0 ) + pTokenD = (pToken2[0] == '.')? NULL : pToken2; + else if ( pToken[1] == 'Q' && pToken[2] == 0 ) + pTokenQ = (pToken2[0] == '.')? NULL : pToken2; + else if ( pToken[1] == 'Q' && pToken[2] == 'N' && pToken[3] == 0 ) + pTokenQN = (pToken2[0] == '.')? NULL : pToken2; + else if ( pToken[1] == 'C' && pToken[2] == 'K' && pToken[3] == 0 ) {} + else + assert( 0 ); + if ( pToken2[0] != '.' ) + k++; + } + + if ( pTokenD == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 1 ); + sprintf( p->sError, "Cannot read pin D of the latch \"%s\".", pLatchName ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + if ( pTokenQ == NULL && pTokenQN == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 1 ); + sprintf( p->sError, "Cannot read pins Q/QN of the latch \"%s\".", pLatchName ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + if ( (pTokenRN == NULL) ^ (pTokenSN == NULL) ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 1 ); + sprintf( p->sError, "Cannot read pins RN/SN of the latch \"%s\".", pLatchName ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + if ( Abc_NtkFindNet( pNtk, pTokenD ) == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find latch input net \"%s\".", pTokenD ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + + // create the latch + pLatch = Io_ReadCreateLatch( pNtk, pTokenD, pLatchName ); + + // create the buffer if Q signal is available + if ( pTokenQ ) + { + pNet = Abc_NtkFindNet( pNtk, pTokenQ ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find latch output net \"%s\".", pTokenQ ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + Io_ReadCreateBuf( pNtk, pLatchName, pTokenQ ); + } + if ( pTokenQN ) + { + pNet = Abc_NtkFindNet( pNtk, pTokenQN ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot find latch output net \"%s\".", pTokenQN ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + Io_ReadCreateInv( pNtk, pLatchName, pTokenQN ); + } + + // set the initial value + if ( pTokenRN == NULL && pTokenSN == NULL ) + Abc_LatchSetInitDc( pLatch ); + else + { + fRN1 = (strcmp( pTokenRN, "1'b1" ) == 0); + fSN1 = (strcmp( pTokenSN, "1'b1" ) == 0); + if ( fRN1 && fSN1 ) + Abc_LatchSetInitDc( pLatch ); + else if ( fRN1 ) + Abc_LatchSetInit1( pLatch ); + else if ( fSN1 ) + Abc_LatchSetInit0( pLatch ); + else + { + p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 ); + sprintf( p->sError, "Cannot read the initial value of latch \"%s\".", pLatchName ); + Io_ReadVerPrintErrorMessage( p ); + return 0; + } + } + return 1; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index 4f9f2e9f..132684cc 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -25,440 +25,9 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// -/**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, 0 ); - 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.] @@ -509,36 +78,11 @@ Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ) 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).] + Description [] SideEffects [] @@ -547,55 +91,15 @@ Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ) ***********************************************************************/ Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) { - Abc_Obj_t * pLatch, * pTerm, * pNet; + Abc_Obj_t * pLatch, * pNet; + // create a new latch and add it to the network + pLatch = Abc_NtkCreateLatch( pNtk ); // 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 ); + Abc_ObjAddFanin( pLatch, pNet ); // 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 ); + Abc_ObjAddFanin( pNet, pLatch ); return pLatch; } @@ -642,7 +146,7 @@ Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesI 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); + pTerm = fConst1? Abc_NodeCreateConst1(pNtk) : Abc_NodeCreateConst0(pNtk); pNet = Abc_NtkFindNet(pNtk, pName); assert( pNet ); Abc_ObjAddFanin( pNet, pTerm ); return pTerm; @@ -663,7 +167,7 @@ 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); + pNode = Abc_NodeCreateInv(pNtk, pNet); pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); Abc_ObjAddFanin( pNet, pNode ); return pNode; @@ -684,67 +188,12 @@ 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); + pNode = Abc_NodeCreateBuf(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 758e5335..00000000 --- a/src/base/io/ioWriteAiger.c +++ /dev/null @@ -1,375 +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; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**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; -} - -/**Function************************************************************* - - Synopsis [Create the array of literals to be written.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Io_WriteAigerLiterals( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vLits; - Abc_Obj_t * pObj, * pDriver; - int i; - vLits = Vec_IntAlloc( Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachLatchInput( pNtk, pObj, i ) - { - pDriver = Abc_ObjFanin0(pObj); - Vec_IntPush( vLits, Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pDriver = Abc_ObjFanin0(pObj); - Vec_IntPush( vLits, Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); - } - return vLits; -} - -/**Function************************************************************* - - Synopsis [Creates the binary encoded array of literals.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Str_t * Io_WriteEncodeLiterals( Vec_Int_t * vLits ) -{ - Vec_Str_t * vBinary; - int Pos = 0, Lit, LitPrev, Diff, i; - vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) ); - LitPrev = Vec_IntEntry( vLits, 0 ); - Pos = Io_WriteAigerEncode( Vec_StrArray(vBinary), Pos, LitPrev ); - Vec_IntForEachEntryStart( vLits, Lit, i, 1 ) - { - Diff = Lit - LitPrev; - Diff = (Lit < LitPrev)? -Diff : Diff; - Diff = (Diff << 1) | (int)(Lit < LitPrev); - Pos = Io_WriteAigerEncode( Vec_StrArray(vBinary), Pos, Diff ); - LitPrev = Lit; - if ( Pos + 10 > vBinary->nCap ) - Vec_StrGrow( vBinary, vBinary->nCap+1 ); - } - vBinary->nSize = Pos; -/* - // verify - { - extern Vec_Int_t * Io_WriteDecodeLiterals( char ** ppPos, int nEntries ); - char * pPos = Vec_StrArray( vBinary ); - Vec_Int_t * vTemp = Io_WriteDecodeLiterals( &pPos, Vec_IntSize(vLits) ); - for ( i = 0; i < Vec_IntSize(vLits); i++ ) - { - int Entry1 = Vec_IntEntry(vLits,i); - int Entry2 = Vec_IntEntry(vTemp,i); - assert( Entry1 == Entry2 ); - } - } -*/ - return vBinary; -} - -/**Function************************************************************* - - Synopsis [Writes the AIG in the binary AIGER format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact ) -{ - 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%s %u %u %u %u %u\n", - fCompact? "2" : "", - 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 - - if ( !fCompact ) - { - // 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) ) ); - } - } - else - { - Vec_Int_t * vLits = Io_WriteAigerLiterals( pNtk ); - Vec_Str_t * vBinary = Io_WriteEncodeLiterals( vLits ); - fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); - Vec_StrFree( vBinary ); - Vec_IntFree( vLits ); - } - - // write the nodes into the buffer - Pos = 0; - nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge - pBuffer = ALLOC( unsigned 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, (unsigned)(uLit - uLit1) ); - Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(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 ); -} - -//////////////////////////////////////////////////////////////////////// -/// 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 index 4b766a47..df79227d 100644 --- a/src/base/io/ioWriteBench.c +++ b/src/base/io/ioWriteBench.c @@ -24,16 +24,11 @@ /// 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 ); +static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -52,11 +47,6 @@ 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 ) { @@ -99,7 +89,7 @@ int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ) 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))) ); + Abc_ObjName(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)) ); // write internal nodes pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); @@ -158,176 +148,6 @@ int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * 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 index c0c29d65..7d6815b9 100644 --- a/src/base/io/ioWriteBlif.c +++ b/src/base/io/ioWriteBlif.c @@ -26,19 +26,16 @@ /// 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_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode ); 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_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode ); static void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -56,7 +53,7 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) { Abc_Ntk_t * pNtkTemp; // derive the netlist - pNtkTemp = Abc_NtkToNetlist(pNtk); + pNtkTemp = Abc_NtkLogicToNetlist(pNtk); if ( pNtkTemp == NULL ) { fprintf( stdout, "Writing BLIF has failed.\n" ); @@ -79,52 +76,17 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) ***********************************************************************/ void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) { + Abc_Ntk_t * pExdc; 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, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); // write the network Io_NtkWriteOne( pFile, pNtk, fWriteLatches ); @@ -138,6 +100,7 @@ void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) } // finalize the file fprintf( pFile, ".end\n" ); + fclose( pFile ); } /**Function************************************************************* @@ -155,7 +118,7 @@ void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) { ProgressBar * pProgress; Abc_Obj_t * pNode, * pLatch; - int i, Length; + int i; // write the PIs fprintf( pFile, ".inputs" ); @@ -167,21 +130,6 @@ void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) 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 ); @@ -194,23 +142,12 @@ void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) 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 ); + Io_NtkWriteNode( pFile, pNode ); } Extra_ProgressBarStop( pProgress ); } @@ -323,8 +260,6 @@ void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) { 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; @@ -342,80 +277,6 @@ void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) } } -/**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************************************************************* @@ -432,14 +293,14 @@ 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) ); + pNetLi = Abc_ObjFanin0( pLatch ); + pNetLo = 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 ); + fprintf( pFile, " %d\n", Reset ); } @@ -454,13 +315,13 @@ void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ) SeeAlso [] ***********************************************************************/ -void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ) +void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode ) { if ( Abc_NtkHasMapping(pNode->pNtk) ) { // write the .gate line fprintf( pFile, ".gate" ); - Io_NtkWriteNodeGate( pFile, pNode, Length ); + Io_NtkWriteNodeGate( pFile, pNode ); fprintf( pFile, "\n" ); } else @@ -485,17 +346,17 @@ void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ) SeeAlso [] ***********************************************************************/ -void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) +void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode ) { Mio_Gate_t * pGate = pNode->pData; Mio_Pin_t * pGatePin; int i; // write the node - fprintf( pFile, " %-*s ", Length, Mio_GateReadName(pGate) ); + fprintf( pFile, " %s ", 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) ) ); + fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName(pNode) ); } /**Function************************************************************* 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 index e1b2d956..09824f38 100644 --- a/src/base/io/ioWriteCnf.c +++ b/src/base/io/ioWriteCnf.c @@ -19,16 +19,13 @@ ***********************************************************************/ #include "io.h" -#include "satSolver.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * s_pNtk = NULL; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -42,71 +39,33 @@ static Abc_Ntk_t * s_pNtk = NULL; SeeAlso [] ***********************************************************************/ -int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName, int fAllPrimes ) +int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName ) { - 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 ) + solver * pSat; + if ( !Abc_NtkIsBddLogic(pNtk) ) { - fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" ); + fprintf( stdout, "Io_WriteCnf(): Currently can only process logic networks with BDDs.\n" ); return 0; } - if ( Abc_NtkLatchNum(pNtk) != 0 ) + if ( Abc_NtkPoNum(pNtk) != 1 ) { - fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" ); + fprintf( stdout, "Io_WriteCnf(): Currently can only solve the miter (the network with one PO).\n" ); return 0; } - if ( Abc_NtkNodeNum(pNtk) == 0 ) + if ( Abc_NtkLatchNum(pNtk) != 0 ) { - fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" ); + fprintf( stdout, "Io_WriteCnf(): Currently can only solve the miter for combinational circuits.\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; - } + pSat = Abc_NtkMiterSatCreate( pNtk ); // write the clauses - s_pNtk = pNtk; - Sat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 ); - s_pNtk = NULL; + Asat_SolverWriteDimacs( pSat, pFileName ); // free the solver - sat_solver_delete( pSat ); + 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 index 8ae3cc42..97258c81 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -19,23 +19,18 @@ ***********************************************************************/ #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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Writes the graph structure of network for DOT.] + Synopsis [Writes the graph structure of AIG in DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] @@ -45,36 +40,13 @@ static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ); 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 ) +void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName ) { FILE * pFile; - Abc_Obj_t * pNode, * pFanin; - char * pSopString; - int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; + Abc_Obj_t * pNode, * pTemp, * pPrev; + int LevelMin, LevelMax, fHasCos, Level, i; 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" ); @@ -94,16 +66,6 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho 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; @@ -111,17 +73,6 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho 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; @@ -151,17 +102,14 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho } // write the DOT header - fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); + fprintf( pFile, "# %s\n", "AIG generated by ABC" ); fprintf( pFile, "\n" ); - fprintf( pFile, "digraph network {\n" ); + fprintf( pFile, "digraph AIG {\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, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); @@ -210,7 +158,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); - fprintf( pFile, "%s", "Network structure visualized by ABC" ); + fprintf( pFile, "%s", "AIG generated by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); @@ -228,10 +176,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho 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, "The set contains %d nodes and spans %d levels.", vNodes->nSize, LevelMax - LevelMin ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); @@ -246,16 +191,14 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); - // generate the PO nodes + // generat 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") ); + fprintf( pFile, " Node%d%s [label = \"%s%s\"", pNode->Id, + (Abc_ObjIsLatch(pNode)? "_in":""), Abc_ObjName(pNode), (Abc_ObjIsLatch(pNode)? "_in":"") ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsLatch(pNode)? "box":"invtriangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); @@ -277,19 +220,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho { 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, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); @@ -307,27 +238,14 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMin ); - // generate the PO nodes + // generat 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") ); + fprintf( pFile, " Node%d%s [label = \"%s%s\"", pNode->Id, + (Abc_ObjIsLatch(pNode)? "_out":""), Abc_ObjName(pNode), (Abc_ObjIsLatch(pNode)? "_out":"") ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsLatch(pNode)? "box":"triangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); @@ -344,387 +262,48 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho { if ( (int)pNode->Level != LevelMax ) continue; - fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, + (Abc_ObjIsLatch(pNode)? "_in":"") ); } // generate edges Vec_PtrForEachEntry( vNodes, pNode, i ) { - if ( Abc_ObjIsLatch(pNode) ) + if ( Abc_ObjFaninNum(pNode) == 0 ) continue; - Abc_ObjForEachFanin( pNode, pFanin, k ) + // generate the edge from this node to the next + if ( Abc_ObjFanin0(pNode)->fMarkC ) { - 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, "Node%d%s", pNode->Id, (Abc_ObjIsLatch(pNode)? "_in":"") ); 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, "Node%d%s", Abc_ObjFaninId0(pNode), (Abc_ObjIsLatch(Abc_ObjFanin0(pNode))? "_out":"") ); + fprintf( pFile, " [style = %s]", Abc_ObjFaninC0(pNode)? "dotted" : "bold" ); 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; + if ( Abc_ObjFaninNum(pNode) == 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 ) + // generate the edge from this node to the next + if ( Abc_ObjFanin1(pNode)->fMarkC ) { - 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, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Abc_ObjFaninId1(pNode), (Abc_ObjIsLatch(Abc_ObjFanin1(pNode))? "_out":"") ); + fprintf( pFile, " [style = %s]", Abc_ObjFaninC1(pNode)? "dotted" : "bold" ); + 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 ) + // generate the edges between the equivalent nodes + pPrev = pNode; + for ( pTemp = pNode->pData; pTemp; pTemp = pTemp->pData ) { - fCompl = 0; - if ( Abc_NtkIsStrash(pNtk) ) + if ( pTemp->fMarkC ) { - if ( Abc_ObjIsBi(pFanin) ) - fCompl = Abc_ObjFaninC(pFanin, k); - else - fCompl = Abc_ObjFaninC(pNode, k); + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pTemp->Id ); + fprintf( pFile, " [style = %s]", (pPrev->fPhase ^ pTemp->fPhase)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + pPrev = pTemp; } - 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" ); } } @@ -739,67 +318,6 @@ void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho 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; } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/ioWriteEqn.c b/src/base/io/ioWriteEqn.c index 95c54577..6c2893b5 100644 --- a/src/base/io/ioWriteEqn.c +++ b/src/base/io/ioWriteEqn.c @@ -25,12 +25,12 @@ //////////////////////////////////////////////////////////////////////// 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 ); +static void Io_NtkWriteEqnPis( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnPos( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnNode( FILE * pFile, Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -48,14 +48,10 @@ void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; - assert( Abc_NtkIsAigNetlist(pNtk) ); + assert( Abc_NtkIsSopNetlist(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 ) @@ -84,37 +80,28 @@ void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ) ***********************************************************************/ void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) { - Vec_Vec_t * vLevels; ProgressBar * pProgress; - Abc_Obj_t * pNode, * pFanin; - int i, k; + Abc_Obj_t * pNode; + int i; // write the PIs fprintf( pFile, "INORDER =" ); - Io_NtkWriteEqnCis( pFile, pNtk ); + Io_NtkWriteEqnPis( pFile, pNtk ); fprintf( pFile, ";\n" ); // write the POs fprintf( pFile, "OUTORDER =" ); - Io_NtkWriteEqnCos( pFile, pNtk ); + Io_NtkWriteEqnPos( 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" ); + Io_NtkWriteEqnNode( pFile, pNode ); } Extra_ProgressBarStop( pProgress ); - Vec_VecFree( vLevels ); } @@ -129,7 +116,7 @@ void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ) +void Io_NtkWriteEqnPis( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pTerm, * pNet; int LineLength; @@ -169,7 +156,7 @@ void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ) +void Io_NtkWriteEqnPos( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pTerm, * pNet; int LineLength; @@ -200,51 +187,73 @@ void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ) /**Function************************************************************* - Synopsis [Make sure the network does not have offending names.] + Synopsis [Write the node into a file.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ) +void Io_NtkWriteEqnNode( FILE * pFile, Abc_Obj_t * pNode ) { - Abc_Obj_t * pObj; - char * pName; - int i, k, Length; - int RetValue = 1; + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pCube; + int Value, fFirstLit, i; + + fprintf( pFile, "%s = ", Abc_ObjName(pNode) ); + + if ( Abc_SopIsConst0(pNode->pData) ) + { + fprintf( pFile, "0;\n" ); + return; + } + if ( Abc_SopIsConst1(pNode->pData) ) + { + fprintf( pFile, "1;\n" ); + return; + } - // make sure the network does not have proper names, such as "0" or "1" or containing parantheses - Abc_NtkForEachObj( pNtk, pObj, i ) + NameCounter = 0; + LineLength = strlen(Abc_ObjName(pNode)) + 3; + Abc_SopForEachCube( pNode->pData, Abc_ObjFaninNum(pNode), pCube ) { - pName = Nm_ManFindNameById(pNtk->pManName, i); - if ( pName == NULL ) - continue; - Length = strlen(pName); - if ( pName[0] == '0' || pName[0] == '1' ) + if ( pCube != pNode->pData ) { - RetValue = 0; - break; + fprintf( pFile, " + " ); + LineLength += 3; } - for ( k = 0; k < Length; k++ ) - if ( pName[k] == '(' || pName[k] == ')' || pName[k] == '!' || pName[k] == '*' || pName[k] == '+' ) - { - RetValue = 0; - break; + + // add the cube + fFirstLit = 1; + Abc_CubeForEachVar( pCube, Value, i ) + { + if ( Value == '-' ) + continue; + pNet = Abc_ObjFanin( pNode, i ); + // get the line length after this name is written + AddedLength = !fFirstLit + (Value == '0') + strlen(Abc_ObjName(pNet)); + if ( NameCounter && LineLength + AddedLength + 6 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n " ); + // reset the line length + LineLength = 0; + NameCounter = 0; } - 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" ); + fprintf( pFile, "%s%s%s", (fFirstLit? "": "*"), ((Value == '0')? "!":""), Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + fFirstLit = 0; + } } - return RetValue; + fprintf( pFile, ";\n" ); } + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/ioWriteGml.c b/src/base/io/ioWriteGml.c index dc897300..ab9f1143 100644 --- a/src/base/io/ioWriteGml.c +++ b/src/base/io/ioWriteGml.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* 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 index b119751c..25a68978 100644 --- a/src/base/io/ioWritePla.c +++ b/src/base/io/ioWritePla.c @@ -27,7 +27,7 @@ static int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -47,7 +47,7 @@ int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName ) FILE * pFile; assert( Abc_NtkIsSopNetlist(pNtk) ); - assert( Abc_NtkLevel(pNtk) == 1 ); + assert( Abc_NtkGetLevelNum(pNtk) == 1 ); pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) @@ -88,7 +88,7 @@ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) nProducts = 0; Abc_NtkForEachCo( pNtk, pNode, i ) { - pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + pDriver = Abc_ObjFanin0Ntk(pNode); if ( !Abc_ObjIsNode(pDriver) ) { nProducts++; @@ -138,10 +138,9 @@ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) pCubeOut[i] = '1'; // consider special cases of nodes - pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + pDriver = Abc_ObjFanin0Ntk(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] = '-'; @@ -153,29 +152,17 @@ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) 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 ); @@ -184,8 +171,6 @@ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) // clean the CI nodes Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = NULL; - free( pCubeIn ); - free( pCubeOut ); return 1; } diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c deleted file mode 100644 index 9e71e3e4..00000000 --- a/src/base/io/ioWriteVerilog.c +++ /dev/null @@ -1,639 +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" ); - // 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/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 index bb35a7fc..34582473 100644 --- a/src/base/io/module.make +++ b/src/base/io/module.make @@ -1,25 +1,16 @@ SRC += src/base/io/io.c \ - src/base/io/ioReadAiger.c \ - src/base/io/ioReadBaf.c \ + src/base/io/ioRead.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 + src/base/io/ioWritePla.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 index 8f43c605..0622a3bd 100644 --- a/src/base/main/main.c +++ b/src/base/main/main.c @@ -20,9 +20,6 @@ #include "mainInt.h" -// this line should be included in the library project -//#define _LIB - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -30,11 +27,9 @@ static int TypeCheck( Abc_Frame_t * pAbc, char * s); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// -#ifndef _LIB - /**Function************************************************************* Synopsis [The main() procedure.] @@ -53,14 +48,11 @@ int main( int argc, char * argv[] ) 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 @@ -72,24 +64,24 @@ int main( int argc, char * argv[] ) fInitRead = 0; fFinalWrite = 0; sInFile = sOutFile = NULL; - sprintf( sReadCmd, "read" ); - sprintf( sWriteCmd, "write" ); + sprintf( sReadCmd, "read_blif_mv" ); + sprintf( sWriteCmd, "write_blif_mv" ); - Extra_UtilGetoptReset(); - while ((c = Extra_UtilGetopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) { + util_getopt_reset(); + while ((c = util_getopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) { switch(c) { case 'c': - strcpy( sCommandUsr, globalUtilOptarg ); + strcpy( sCommandUsr, util_optarg ); fBatch = 1; break; case 'f': - sprintf(sCommandUsr, "source %s", globalUtilOptarg); + sprintf(sCommandUsr, "source %s", util_optarg); fBatch = 1; break; case 'F': - sprintf(sCommandUsr, "source -x %s", globalUtilOptarg); + sprintf(sCommandUsr, "source -x %s", util_optarg); fBatch = 1; break; @@ -98,7 +90,7 @@ int main( int argc, char * argv[] ) break; case 'o': - sOutFile = globalUtilOptarg; + sOutFile = util_optarg; fFinalWrite = 1; break; @@ -107,12 +99,12 @@ int main( int argc, char * argv[] ) break; case 't': - if ( TypeCheck( pAbc, globalUtilOptarg ) ) + if ( TypeCheck( pAbc, util_optarg ) ) { - if ( !strcmp(globalUtilOptarg, "none") == 0 ) + if ( !strcmp(util_optarg, "none") == 0 ) { fInitRead = 1; - sprintf( sReadCmd, "read_%s", globalUtilOptarg ); + sprintf( sReadCmd, "read_%s", util_optarg ); } } else { @@ -122,12 +114,12 @@ int main( int argc, char * argv[] ) break; case 'T': - if ( TypeCheck( pAbc, globalUtilOptarg ) ) + if ( TypeCheck( pAbc, util_optarg ) ) { - if (!strcmp(globalUtilOptarg, "none") == 0) + if (!strcmp(util_optarg, "none") == 0) { fFinalWrite = 1; - sprintf( sWriteCmd, "write_%s", globalUtilOptarg); + sprintf( sWriteCmd, "write_%s", util_optarg); } } else { @@ -151,14 +143,14 @@ int main( int argc, char * argv[] ) { pAbc->fBatchMode = 1; - if (argc - globalUtilOptind == 0) + if (argc - util_optind == 0) { sInFile = NULL; } - else if (argc - globalUtilOptind == 1) + else if (argc - util_optind == 1) { fInitRead = 1; - sInFile = argv[globalUtilOptind]; + sInFile = argv[util_optind]; } else { @@ -217,11 +209,14 @@ int main( int argc, char * argv[] ) break; } } - + // if the memory should be freed, quit packages - if ( fStatus < 0 ) + if ( fStatus == -2 ) { - Abc_Stop(); + // perform uninitializations + Abc_FrameEnd( pAbc ); + // stop the framework + Abc_FrameDeallocate( pAbc ); } return 0; @@ -231,58 +226,6 @@ usage: 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******************************************************************** diff --git a/src/base/main/main.h b/src/base/main/main.h index 4433a8b4..0d47dec5 100644 --- a/src/base/main/main.h +++ b/src/base/main/main.h @@ -21,10 +21,6 @@ #ifndef __MAIN_H__ #define __MAIN_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// TYPEDEFS /// //////////////////////////////////////////////////////////////////////// @@ -44,10 +40,17 @@ typedef struct Abc_Frame_t_ Abc_Frame_t; // it is used to catch memory leaks on Windows #include "leaks.h" +// standard includes +#include +#include + +// includes from GLU +#include "util.h" +#include "st.h" + // data structure packages #include "extra.h" #include "vec.h" -#include "st.h" // core packages #include "abc.h" @@ -63,25 +66,20 @@ typedef struct Abc_Frame_t_ Abc_Frame_t; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// -/*=== main.c ===========================================================*/ -extern void Abc_Start(); -extern void Abc_Stop(); - -/*=== mainFrame.c ===========================================================*/ -extern Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ); +/*=== mvFrame.c ===========================================================*/ +extern Abc_Ntk_t * Abc_FrameReadNet( 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 ); @@ -92,12 +90,11 @@ 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 Abc_Ntk_t * Abc_FrameReadNtkStore(); +extern int Abc_FrameReadNtkStoreSize(); 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 ); @@ -108,15 +105,10 @@ 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 /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c index eae8b7a6..77c9f579 100644 --- a/src/base/main/mainFrame.c +++ b/src/base/main/mainFrame.c @@ -29,7 +29,7 @@ static Abc_Frame_t * s_GlobalFrame = NULL; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -43,20 +43,20 @@ static Abc_Frame_t * s_GlobalFrame = NULL; SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_FrameReadStore() { return s_GlobalFrame->vStore; } -int Abc_FrameReadStoreSize() { return Vec_PtrSize(s_GlobalFrame->vStore); } +Abc_Ntk_t * Abc_FrameReadNtkStore() { return s_GlobalFrame->pStored; } +int Abc_FrameReadNtkStoreSize() { return s_GlobalFrame->nStored; } 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; } +void * Abc_FrameReadManDd() { return s_GlobalFrame->dd; } +void * Abc_FrameReadManDec() { return s_GlobalFrame->pManDec; } char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); } +void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ) { s_GlobalFrame->pStored = pNtk; } +void Abc_FrameSetNtkStoreSize( int nStored ) { s_GlobalFrame->nStored = nStored; } 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************************************************************* @@ -97,8 +97,7 @@ bool Abc_FrameIsFlagEnabled( char * pFlag ) 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) ); @@ -111,13 +110,9 @@ Abc_Frame_t * Abc_FrameAllocate() // 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(); + p->pManDec = Dec_ManStart(); + p->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); return p; } @@ -135,20 +130,11 @@ Abc_Frame_t * Abc_FrameAllocate() ***********************************************************************/ 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 ); + Dec_ManStop( p->pManDec ); + Extra_StopManager( p->dd ); Abc_FrameDeleteAllNetworks( p ); free( p ); - s_GlobalFrame = NULL; + p = NULL; } /**Function************************************************************* @@ -166,22 +152,6 @@ void Abc_FrameRestart( Abc_Frame_t * p ) { } -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_FrameShowProgress( Abc_Frame_t * p ) -{ - return Abc_FrameIsFlagEnabled( "progressbar" ); -} - /**Function************************************************************* @@ -194,7 +164,7 @@ bool Abc_FrameShowProgress( Abc_Frame_t * p ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ) +Abc_Ntk_t * Abc_FrameReadNet( Abc_Frame_t * p ) { return p->pNtkCur; } @@ -427,7 +397,7 @@ 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 ); + Abc_NtkUnmap( pNtk ); } /**Function************************************************************* @@ -453,7 +423,7 @@ void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ) Abc_NtkDelete( pNtk ); // set the current network empty p->pNtkCur = NULL; -// fprintf( p->Out, "All networks have been deleted.\n" ); + fprintf( p->Out, "All networks have been deleted.\n" ); } /**Function************************************************************* diff --git a/src/base/main/mainInit.c b/src/base/main/mainInit.c index 03953e5b..13710dcb 100644 --- a/src/base/main/mainInit.c +++ b/src/base/main/mainInit.c @@ -14,7 +14,7 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: mainInit.c,v 1.3 2005/09/14 22:53:37 casem Exp $] + Revision [$Id: mainInit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ @@ -38,11 +38,9 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -65,7 +63,6 @@ void Abc_FrameInit( Abc_Frame_t * pAbc ) Map_Init( pAbc ); Mio_Init( pAbc ); Super_Init( pAbc ); - Libs_Init( pAbc ); } @@ -89,7 +86,6 @@ void Abc_FrameEnd( Abc_Frame_t * pAbc ) Map_End( pAbc ); Mio_End( pAbc ); Super_End( pAbc ); - Libs_End( pAbc ); } diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h index 09ad96f3..6b929854 100644 --- a/src/base/main/mainInt.h +++ b/src/base/main/mainInt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __MAIN_INT_H__ -#define __MAIN_INT_H__ +#ifndef __Abc_INT_H__ +#define __Abc_INT_H__ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// @@ -63,7 +63,8 @@ struct Abc_Frame_t_ 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 + Abc_Ntk_t * pStored; // the stored networks + int nStored; // the number of stored networks // decomposition package void * pManDec; // decomposition manager DdManager * dd; // temporary BDD package @@ -71,7 +72,6 @@ struct Abc_Frame_t_ void * pLibLut; // the current LUT library void * pLibGen; // the current genlib void * pLibSuper; // the current supergate library - void * pLibVer; // the current Verilog library }; //////////////////////////////////////////////////////////////////////// @@ -79,12 +79,12 @@ struct Abc_Frame_t_ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mvMain.c ===========================================================*/ @@ -102,8 +102,8 @@ 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 /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index 58cc33ec..9d1201fa 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -20,17 +20,13 @@ #include "mainInt.h" -#ifndef _WIN32 -#include "readline/readline.h" -#endif - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static char * DateReadFromDateString(char * datestr); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -66,18 +62,9 @@ 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************************************************************* @@ -147,72 +134,32 @@ void Abc_UtilsSource( Abc_Frame_t * pAbc ) printf( "Loaded \"abc.rc\" from the grandparent directory.\n" ); } #else - -#if 0 { - char * sPath1, * sPath2; + 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 .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 = util_file_search(".rc", "~/", "r"); + sPath2 = util_file_search(".rc", ".", "r"); - if ( sPath1 && sPath2 ) { - /* ~/.rc == .rc : Source the file only once */ + 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"); } - else { - if (sPath1) { - (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); - } - if (sPath2) { - (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" ); + 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 diff --git a/src/base/main/module.make b/src/base/main/module.make index 367f89f6..59e1315e 100644 --- a/src/base/main/module.make +++ b/src/base/main/module.make @@ -1,5 +1,4 @@ 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 ddc92cc8..00000000 --- a/src/base/seq/seqRetCore.c +++ /dev/null @@ -1,493 +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 ) -{ - extern Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ); - 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 322ce720..00000000 --- a/src/base/ver/verCore.c +++ /dev/null @@ -1,2949 +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_ParseFlopStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ); -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, "dff" ) ) - RetValue = Ver_ParseFlopStandard( pMan, pNtk ); - - 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 [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseFlopStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Obj_t * pNetLi, * pNetLo, * pLatch; - 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 ); - - // parse the output name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // get the net corresponding to this output - pNetLo = Ver_ParseFindNet( pNtk, pWord ); - if ( pNetLo == NULL ) - { - sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ')' ) - { - sprintf( pMan->sError, "Cannot parse the flop." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // skip comma - if ( Symbol != ',' ) - { - sprintf( pMan->sError, "Cannot parse the flop." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - - // parse the output name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // get the net corresponding to this output - pNetLi = Ver_ParseFindNet( pNtk, pWord ); - if ( pNetLi == NULL ) - { - sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - Symbol = Ver_StreamPopChar(p); - if ( Symbol != ')' ) - { - sprintf( pMan->sError, "Cannot parse the flop." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - if ( Ver_StreamPopChar(p) != ';' ) - { - sprintf( pMan->sError, "Cannot parse the flop." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // create the latch - pLatch = Ver_ParseCreateLatch( pNtk, pNetLi, pNetLo ); - Abc_LatchSetInit0( pLatch ); - 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 ) - { -/* - if ( Ver_StreamGetLineNumber(pMan->pReader) == 5967 ) - { - int x = 0; - } -*/ - // 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/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 9b56bb3f..00000000 --- a/src/base/ver/verStream.c +++ /dev/null @@ -1,443 +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 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/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/cuddAPI.c b/src/bdd/cudd/cuddAPI.c index a16b82cf..2acde7cd 100644 --- a/src/bdd/cudd/cuddAPI.c +++ b/src/bdd/cudd/cuddAPI.c @@ -164,7 +164,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddAbs.c b/src/bdd/cudd/cuddAddAbs.c index b256ad0f..27039908 100644 --- a/src/bdd/cudd/cuddAddAbs.c +++ b/src/bdd/cudd/cuddAddAbs.c @@ -32,7 +32,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddApply.c b/src/bdd/cudd/cuddAddApply.c index 60c06de6..67649913 100644 --- a/src/bdd/cudd/cuddAddApply.c +++ b/src/bdd/cudd/cuddAddApply.c @@ -42,7 +42,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddFind.c b/src/bdd/cudd/cuddAddFind.c index 0469b014..3399527a 100644 --- a/src/bdd/cudd/cuddAddFind.c +++ b/src/bdd/cudd/cuddAddFind.c @@ -27,7 +27,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddInv.c b/src/bdd/cudd/cuddAddInv.c index fc4a340b..cb6dbfbe 100644 --- a/src/bdd/cudd/cuddAddInv.c +++ b/src/bdd/cudd/cuddAddInv.c @@ -24,7 +24,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddAddIte.c b/src/bdd/cudd/cuddAddIte.c index 71f8070f..77c4d18a 100644 --- a/src/bdd/cudd/cuddAddIte.c +++ b/src/bdd/cudd/cuddAddIte.c @@ -33,7 +33,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddNeg.c b/src/bdd/cudd/cuddAddNeg.c index bdb08ddc..2420df64 100644 --- a/src/bdd/cudd/cuddAddNeg.c +++ b/src/bdd/cudd/cuddAddNeg.c @@ -26,7 +26,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddAddWalsh.c b/src/bdd/cudd/cuddAddWalsh.c index c6a67e34..980ee215 100644 --- a/src/bdd/cudd/cuddAddWalsh.c +++ b/src/bdd/cudd/cuddAddWalsh.c @@ -26,7 +26,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddAndAbs.c b/src/bdd/cudd/cuddAndAbs.c index 5ec47beb..3a6ce85f 100644 --- a/src/bdd/cudd/cuddAndAbs.c +++ b/src/bdd/cudd/cuddAndAbs.c @@ -24,7 +24,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddAnneal.c b/src/bdd/cudd/cuddAnneal.c index 3d8b56b9..dfc81e86 100644 --- a/src/bdd/cudd/cuddAnneal.c +++ b/src/bdd/cudd/cuddAnneal.c @@ -35,7 +35,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddApa.c b/src/bdd/cudd/cuddApa.c index 47ab51e8..805a4dde 100644 --- a/src/bdd/cudd/cuddApa.c +++ b/src/bdd/cudd/cuddApa.c @@ -28,7 +28,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddApprox.c b/src/bdd/cudd/cuddApprox.c index debcf48b..eb6813ff 100644 --- a/src/bdd/cudd/cuddApprox.c +++ b/src/bdd/cudd/cuddApprox.c @@ -51,7 +51,7 @@ #else #define DBL_MAX_EXP 1024 #endif -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddBddAbs.c b/src/bdd/cudd/cuddBddAbs.c index 9552464e..20a8f15a 100644 --- a/src/bdd/cudd/cuddBddAbs.c +++ b/src/bdd/cudd/cuddBddAbs.c @@ -35,7 +35,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddBddCorr.c b/src/bdd/cudd/cuddBddCorr.c index c99324a8..47395ec7 100644 --- a/src/bdd/cudd/cuddBddCorr.c +++ b/src/bdd/cudd/cuddBddCorr.c @@ -30,7 +30,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddBddIte.c b/src/bdd/cudd/cuddBddIte.c index b44e40de..fe0c6500 100644 --- a/src/bdd/cudd/cuddBddIte.c +++ b/src/bdd/cudd/cuddBddIte.c @@ -44,7 +44,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddBridge.c b/src/bdd/cudd/cuddBridge.c index ccc0893f..e7e5c89f 100644 --- a/src/bdd/cudd/cuddBridge.c +++ b/src/bdd/cudd/cuddBridge.c @@ -44,7 +44,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddCache.c b/src/bdd/cudd/cuddCache.c index d9e40921..6598948a 100644 --- a/src/bdd/cudd/cuddCache.c +++ b/src/bdd/cudd/cuddCache.c @@ -36,7 +36,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddCheck.c b/src/bdd/cudd/cuddCheck.c index aec8246d..3db08dd6 100644 --- a/src/bdd/cudd/cuddCheck.c +++ b/src/bdd/cudd/cuddCheck.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddClip.c b/src/bdd/cudd/cuddClip.c index 4da296ef..3c728a56 100644 --- a/src/bdd/cudd/cuddClip.c +++ b/src/bdd/cudd/cuddClip.c @@ -33,7 +33,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddCof.c b/src/bdd/cudd/cuddCof.c index f79e3f91..0dfeff6c 100644 --- a/src/bdd/cudd/cuddCof.c +++ b/src/bdd/cudd/cuddCof.c @@ -29,7 +29,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddCompose.c b/src/bdd/cudd/cuddCompose.c index 8c858051..11c6cb7b 100644 --- a/src/bdd/cudd/cuddCompose.c +++ b/src/bdd/cudd/cuddCompose.c @@ -55,7 +55,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddDecomp.c b/src/bdd/cudd/cuddDecomp.c index 4fde7392..d9c28482 100644 --- a/src/bdd/cudd/cuddDecomp.c +++ b/src/bdd/cudd/cuddDecomp.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddEssent.c b/src/bdd/cudd/cuddEssent.c index db4b8b49..7bd48c5a 100644 --- a/src/bdd/cudd/cuddEssent.c +++ b/src/bdd/cudd/cuddEssent.c @@ -25,7 +25,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddExact.c b/src/bdd/cudd/cuddExact.c index 6852be68..6a81406b 100644 --- a/src/bdd/cudd/cuddExact.c +++ b/src/bdd/cudd/cuddExact.c @@ -40,7 +40,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddExport.c b/src/bdd/cudd/cuddExport.c index d148be42..d7b9645b 100644 --- a/src/bdd/cudd/cuddExport.c +++ b/src/bdd/cudd/cuddExport.c @@ -35,7 +35,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddGenCof.c b/src/bdd/cudd/cuddGenCof.c index 142ee27e..59ae55d7 100644 --- a/src/bdd/cudd/cuddGenCof.c +++ b/src/bdd/cudd/cuddGenCof.c @@ -46,7 +46,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddGenetic.c b/src/bdd/cudd/cuddGenetic.c index 9fe03dad..8341dcbd 100644 --- a/src/bdd/cudd/cuddGenetic.c +++ b/src/bdd/cudd/cuddGenetic.c @@ -53,7 +53,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddGroup.c b/src/bdd/cudd/cuddGroup.c index 81c05d2c..f84f7881 100644 --- a/src/bdd/cudd/cuddGroup.c +++ b/src/bdd/cudd/cuddGroup.c @@ -49,7 +49,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddHarwell.c b/src/bdd/cudd/cuddHarwell.c index 063f1922..10746186 100644 --- a/src/bdd/cudd/cuddHarwell.c +++ b/src/bdd/cudd/cuddHarwell.c @@ -21,7 +21,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddInit.c b/src/bdd/cudd/cuddInit.c index 8e06a425..aec8d286 100644 --- a/src/bdd/cudd/cuddInit.c +++ b/src/bdd/cudd/cuddInit.c @@ -29,7 +29,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #define CUDD_MAIN #include "cuddInt.h" #undef CUDD_MAIN diff --git a/src/bdd/cudd/cuddInteract.c b/src/bdd/cudd/cuddInteract.c index 96613639..5a4ec79a 100644 --- a/src/bdd/cudd/cuddInteract.c +++ b/src/bdd/cudd/cuddInteract.c @@ -47,7 +47,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddLCache.c b/src/bdd/cudd/cuddLCache.c index 8bd37ba0..72fbd48a 100644 --- a/src/bdd/cudd/cuddLCache.c +++ b/src/bdd/cudd/cuddLCache.c @@ -45,7 +45,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddLevelQ.c b/src/bdd/cudd/cuddLevelQ.c index 3cc8e8d8..c4c621e7 100644 --- a/src/bdd/cudd/cuddLevelQ.c +++ b/src/bdd/cudd/cuddLevelQ.c @@ -50,7 +50,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddLinear.c b/src/bdd/cudd/cuddLinear.c index 7f6b3678..cec7c255 100644 --- a/src/bdd/cudd/cuddLinear.c +++ b/src/bdd/cudd/cuddLinear.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddLiteral.c b/src/bdd/cudd/cuddLiteral.c index 43740690..69594486 100644 --- a/src/bdd/cudd/cuddLiteral.c +++ b/src/bdd/cudd/cuddLiteral.c @@ -25,7 +25,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddMatMult.c b/src/bdd/cudd/cuddMatMult.c index 345e7921..b10975ec 100644 --- a/src/bdd/cudd/cuddMatMult.c +++ b/src/bdd/cudd/cuddMatMult.c @@ -29,7 +29,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddPriority.c b/src/bdd/cudd/cuddPriority.c index 788fc712..bb0b83d3 100644 --- a/src/bdd/cudd/cuddPriority.c +++ b/src/bdd/cudd/cuddPriority.c @@ -43,7 +43,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddRead.c b/src/bdd/cudd/cuddRead.c index 2c4a86d8..eea4c7f3 100644 --- a/src/bdd/cudd/cuddRead.c +++ b/src/bdd/cudd/cuddRead.c @@ -23,7 +23,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddRef.c b/src/bdd/cudd/cuddRef.c index a9241f3d..af08d048 100644 --- a/src/bdd/cudd/cuddRef.c +++ b/src/bdd/cudd/cuddRef.c @@ -38,7 +38,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddReorder.c b/src/bdd/cudd/cuddReorder.c index 1387196f..e2b3470b 100644 --- a/src/bdd/cudd/cuddReorder.c +++ b/src/bdd/cudd/cuddReorder.c @@ -45,7 +45,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSat.c b/src/bdd/cudd/cuddSat.c index 1755a1c1..dde33a5b 100644 --- a/src/bdd/cudd/cuddSat.c +++ b/src/bdd/cudd/cuddSat.c @@ -42,7 +42,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSign.c b/src/bdd/cudd/cuddSign.c index fcaa65c4..62477e7f 100644 --- a/src/bdd/cudd/cuddSign.c +++ b/src/bdd/cudd/cuddSign.c @@ -25,7 +25,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddSolve.c b/src/bdd/cudd/cuddSolve.c index d9c4a2e7..058e0c08 100644 --- a/src/bdd/cudd/cuddSolve.c +++ b/src/bdd/cudd/cuddSolve.c @@ -28,7 +28,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSplit.c b/src/bdd/cudd/cuddSplit.c index e21ea7cb..af7d6372 100644 --- a/src/bdd/cudd/cuddSplit.c +++ b/src/bdd/cudd/cuddSplit.c @@ -32,7 +32,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSubsetHB.c b/src/bdd/cudd/cuddSubsetHB.c index 24d41ce5..43aaf744 100644 --- a/src/bdd/cudd/cuddSubsetHB.c +++ b/src/bdd/cudd/cuddSubsetHB.c @@ -46,7 +46,7 @@ #else #define DBL_MAX_EXP 1024 #endif -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSubsetSP.c b/src/bdd/cudd/cuddSubsetSP.c index 55ee3470..0f7209dd 100644 --- a/src/bdd/cudd/cuddSubsetSP.c +++ b/src/bdd/cudd/cuddSubsetSP.c @@ -41,7 +41,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSymmetry.c b/src/bdd/cudd/cuddSymmetry.c index e5488b17..7b2013e4 100644 --- a/src/bdd/cudd/cuddSymmetry.c +++ b/src/bdd/cudd/cuddSymmetry.c @@ -38,7 +38,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddTable.c b/src/bdd/cudd/cuddTable.c index 7f14aed1..b118b76a 100644 --- a/src/bdd/cudd/cuddTable.c +++ b/src/bdd/cudd/cuddTable.c @@ -54,7 +54,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddUtil.c b/src/bdd/cudd/cuddUtil.c index d5fa18e2..c366d534 100644 --- a/src/bdd/cudd/cuddUtil.c +++ b/src/bdd/cudd/cuddUtil.c @@ -76,7 +76,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddWindow.c b/src/bdd/cudd/cuddWindow.c index 9ceb79b2..3e6d5686 100644 --- a/src/bdd/cudd/cuddWindow.c +++ b/src/bdd/cudd/cuddWindow.c @@ -31,7 +31,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddCount.c b/src/bdd/cudd/cuddZddCount.c index 6c6ec1df..29cf0c14 100644 --- a/src/bdd/cudd/cuddZddCount.c +++ b/src/bdd/cudd/cuddZddCount.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddFuncs.c b/src/bdd/cudd/cuddZddFuncs.c index 9dc27a95..f938e1de 100644 --- a/src/bdd/cudd/cuddZddFuncs.c +++ b/src/bdd/cudd/cuddZddFuncs.c @@ -48,7 +48,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddGroup.c b/src/bdd/cudd/cuddZddGroup.c index 621fa43f..35f28881 100644 --- a/src/bdd/cudd/cuddZddGroup.c +++ b/src/bdd/cudd/cuddZddGroup.c @@ -40,7 +40,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddIsop.c b/src/bdd/cudd/cuddZddIsop.c index f4b057ea..0918461c 100644 --- a/src/bdd/cudd/cuddZddIsop.c +++ b/src/bdd/cudd/cuddZddIsop.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddLin.c b/src/bdd/cudd/cuddZddLin.c index ef2cd298..9369bb05 100644 --- a/src/bdd/cudd/cuddZddLin.c +++ b/src/bdd/cudd/cuddZddLin.c @@ -32,7 +32,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddMisc.c b/src/bdd/cudd/cuddZddMisc.c index 6a4ddd09..d55bb768 100644 --- a/src/bdd/cudd/cuddZddMisc.c +++ b/src/bdd/cudd/cuddZddMisc.c @@ -33,7 +33,7 @@ ******************************************************************************/ #include -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddPort.c b/src/bdd/cudd/cuddZddPort.c index 6d4a3236..1700ab2b 100644 --- a/src/bdd/cudd/cuddZddPort.c +++ b/src/bdd/cudd/cuddZddPort.c @@ -32,7 +32,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddReord.c b/src/bdd/cudd/cuddZddReord.c index e2da37f2..e14ae2ad 100644 --- a/src/bdd/cudd/cuddZddReord.c +++ b/src/bdd/cudd/cuddZddReord.c @@ -46,7 +46,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddSetop.c b/src/bdd/cudd/cuddZddSetop.c index f1bd72f3..cf05210f 100644 --- a/src/bdd/cudd/cuddZddSetop.c +++ b/src/bdd/cudd/cuddZddSetop.c @@ -46,7 +46,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddSymm.c b/src/bdd/cudd/cuddZddSymm.c index 54019892..c9ffaab4 100644 --- a/src/bdd/cudd/cuddZddSymm.c +++ b/src/bdd/cudd/cuddZddSymm.c @@ -40,7 +40,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddUtil.c b/src/bdd/cudd/cuddZddUtil.c index 616d16d4..0795f123 100644 --- a/src/bdd/cudd/cuddZddUtil.c +++ b/src/bdd/cudd/cuddZddUtil.c @@ -35,7 +35,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/testcudd.c b/src/bdd/cudd/testcudd.c index d8affadc..451bb190 100644 --- a/src/bdd/cudd/testcudd.c +++ b/src/bdd/cudd/testcudd.c @@ -23,7 +23,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "cuddInt.h" diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h index b73b81ab..5396bacd 100644 --- a/src/bdd/dsd/dsd.h +++ b/src/bdd/dsd/dsd.h @@ -28,12 +28,8 @@ #ifndef __DSD_H__ #define __DSD_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// -/// TYPEDEF DEFINITIONS /// +/// TYPEDEF DEFITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Dsd_Manager_t_ Dsd_Manager_t; @@ -59,14 +55,14 @@ enum Dsd_Type_t_ { }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // 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))) +#define Dsd_IsComplement(p) (((int)((long) (p) & 01))) +#define Dsd_Regular(p) ((Dsd_Node_t *)((unsigned)(p) & ~01)) +#define Dsd_Not(p) ((Dsd_Node_t *)((long)(p) ^ 01)) +#define Dsd_NotCond(p,c) ((Dsd_Node_t *)((long)(p) ^ (c))) //////////////////////////////////////////////////////////////////////// /// ITERATORS /// @@ -80,7 +76,7 @@ enum Dsd_Type_t_ { Index++ ) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== dsdApi.c =======================================================*/ @@ -95,7 +91,6 @@ 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 ); @@ -105,7 +100,6 @@ 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 ); @@ -114,16 +108,11 @@ extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, in 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 /// //////////////////////////////////////////////////////////////////////// + +#endif \ No newline at end of file diff --git a/src/bdd/dsd/dsdApi.c b/src/bdd/dsd/dsdApi.c index d1c90e23..daf3080f 100644 --- a/src/bdd/dsd/dsdApi.c +++ b/src/bdd/dsd/dsdApi.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -89,7 +89,6 @@ void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ){ p->Mark = Mark; } ***********************************************************************/ 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; } //////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdCheck.c b/src/bdd/dsd/dsdCheck.c index 58b824d2..608aa2e3 100644 --- a/src/bdd/dsd/dsdCheck.c +++ b/src/bdd/dsd/dsdCheck.c @@ -43,7 +43,7 @@ static Dds_Cache_t * pCache; static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** @@ -82,7 +82,7 @@ void Dsd_CheckCacheAllocate( int nEntries ) /**Function******************************************************************** - Synopsis [Deallocates the local cache.] + Synopsis [Delocates the local cache.] Description [] diff --git a/src/bdd/dsd/dsdInt.h b/src/bdd/dsd/dsdInt.h index 62ce7e99..5008c24e 100644 --- a/src/bdd/dsd/dsdInt.h +++ b/src/bdd/dsd/dsdInt.h @@ -23,7 +23,7 @@ #include "dsd.h" //////////////////////////////////////////////////////////////////////// -/// TYPEDEF DEFINITIONS /// +/// TYPEDEF DEFITIONS /// //////////////////////////////////////////////////////////////////////// typedef unsigned char byte; @@ -42,7 +42,6 @@ struct Dsd_Manager_t_ 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 }; @@ -59,7 +58,7 @@ struct Dsd_Node_t_ }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// #define MAXINPUTS 1000 @@ -83,9 +82,9 @@ 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 /// //////////////////////////////////////////////////////////////////////// + +#endif \ No newline at end of file diff --git a/src/bdd/dsd/dsdMan.c b/src/bdd/dsd/dsdMan.c index 6e43f0f4..4529e75a 100644 --- a/src/bdd/dsd/dsdMan.c +++ b/src/bdd/dsd/dsdMan.c @@ -73,7 +73,6 @@ Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ) 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; diff --git a/src/bdd/dsd/dsdProc.c b/src/bdd/dsd/dsdProc.c index 543ad387..08c029e1 100644 --- a/src/bdd/dsd/dsdProc.c +++ b/src/bdd/dsd/dsdProc.c @@ -1255,7 +1255,7 @@ EXIT: s_CacheEntries++; -/* +#if 0 if ( dsdKernelVerifyDecomposition(dd, pThis) == 0 ) { // write the function, for which verification does not work @@ -1277,7 +1277,7 @@ EXIT: cuddWriteFunctionSop( stdout, dd, zNewFunc, -1, dd->size, "1", s_pVarMask ); Cudd_RecursiveDerefZdd( dd, zNewFunc ); } -*/ +#endif } diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c index 2855d68d..7905cbdd 100644 --- a/src/bdd/dsd/dsdTree.c +++ b/src/bdd/dsd/dsdTree.c @@ -29,7 +29,7 @@ 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 /// @@ -241,58 +241,6 @@ void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ) 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.] @@ -683,21 +631,27 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp 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 ); + fprintf( pFile, "%s: ", pOutputName ); pInputNums = ALLOC( int, pNode->nDecs ); if ( pNode->Type == DSD_NODE_CONST1 ) { - fprintf( pFile, " Constant 1.\n" ); + if ( fComp ) + fprintf( pFile, " Constant 0.\n" ); + else + fprintf( pFile, " Constant 1.\n" ); } else if ( pNode->Type == DSD_NODE_BUF ) { + if ( fComp ) + fprintf( pFile, " NOT(" ); + else + fprintf( pFile, " " ); if ( fShortNames ) - fprintf( pFile, "%d", 'a' + pNode->S->index ); + fprintf( pFile, "%d", pNode->S->index ); else fprintf( pFile, "%s", pInputNames[pNode->S->index] ); + if ( fComp ) + fprintf( pFile, ")" ); fprintf( pFile, "\n" ); } else if ( pNode->Type == DSD_NODE_PRIME ) @@ -710,25 +664,25 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp 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 ( fCompNew ) + fprintf( pFile, " NOT(" ); + else + fprintf( pFile, " " ); if ( fShortNames ) fprintf( pFile, "%d", pInput->S->index ); else fprintf( pFile, "%s", pInputNames[pInput->S->index] ); + if ( fCompNew ) + fprintf( pFile, ")" ); } else { pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); + fprintf( pFile, " <%d>", pInputNums[i] ); } - if ( fCompNew ) - fprintf( pFile, ")" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks @@ -736,39 +690,43 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); + Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); } } else if ( pNode->Type == DSD_NODE_OR ) { // print the line - fprintf( pFile, "OR(" ); + if ( fComp ) + fprintf( pFile, "AND(" ); + else + 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 ( fCompNew ) + fprintf( pFile, " NOT(" ); + else + fprintf( pFile, " " ); if ( fShortNames ) - fprintf( pFile, "%c", 'a' + pInput->S->index ); + fprintf( pFile, "%d", pInput->S->index ); else fprintf( pFile, "%s", pInputNames[pInput->S->index] ); + if ( fCompNew ) + fprintf( pFile, ")" ); } else { pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); + fprintf( pFile, " <%d>", pInputNums[i] ); } - if ( fCompNew ) - fprintf( pFile, ")" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks @@ -776,208 +734,43 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); + Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fComp ^ fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); } } else if ( pNode->Type == DSD_NODE_EXOR ) { // print the line - fprintf( pFile, "EXOR(" ); + if ( fComp ) + fprintf( pFile, "NEXOR(" ); + else + 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 ( fCompNew ) + fprintf( pFile, " NOT(" ); + else + fprintf( pFile, " " ); if ( fShortNames ) - fprintf( pFile, "%c", 'a' + pInput->S->index ); + 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 ); - } - } - 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 ); + if ( fCompNew ) + fprintf( pFile, ")" ); } else { pInputNums[i] = (*pSigCounter)++; fprintf( pFile, " <%d>", pInputNums[i] ); } - if ( fCompNew ) - fprintf( pFile, "\'" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks @@ -985,8 +778,9 @@ void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOut if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); + Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); } } free( pInputNums ); diff --git a/src/bdd/epd/epd.c b/src/bdd/epd/epd.c index a80240bc..a843b986 100644 --- a/src/bdd/epd/epd.c +++ b/src/bdd/epd/epd.c @@ -25,7 +25,7 @@ #include #include #include -#include "util_hack.h" +#include "util.h" #include "epd.h" diff --git a/src/bdd/mtr/mtrBasic.c b/src/bdd/mtr/mtrBasic.c index 94105282..2aec8d6b 100644 --- a/src/bdd/mtr/mtrBasic.c +++ b/src/bdd/mtr/mtrBasic.c @@ -33,7 +33,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "mtrInt.h" diff --git a/src/bdd/mtr/mtrGroup.c b/src/bdd/mtr/mtrGroup.c index 363b776b..ae9c5c2f 100644 --- a/src/bdd/mtr/mtrGroup.c +++ b/src/bdd/mtr/mtrGroup.c @@ -33,7 +33,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "util.h" #include "mtrInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/parse/module.make b/src/bdd/parse/module.make index 4f590f01..ea535e6e 100644 --- a/src/bdd/parse/module.make +++ b/src/bdd/parse/module.make @@ -1,3 +1,2 @@ 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 index 4923fbdd..8364e782 100644 --- a/src/bdd/parse/parse.h +++ b/src/bdd/parse/parse.h @@ -36,19 +36,18 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== parseCore.c =============================================================*/ extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks, char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ); -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/bdd/parse/parseCore.c b/src/bdd/parse/parseCore.c index 21a37070..d60687a3 100644 --- a/src/bdd/parse/parseCore.c +++ b/src/bdd/parse/parseCore.c @@ -89,7 +89,7 @@ static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* 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 index 17f48375..6e6c49b0 100644 --- a/src/bdd/parse/parseInt.h +++ b/src/bdd/parse/parseInt.h @@ -47,18 +47,18 @@ typedef struct ParseStackOpStruct Parse_StackOp_t; // the operation stack //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== 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_StackFnPush ( Parse_StackFn_t * p, DdNode * bFunc ); +extern DdNode * Parse_StackFnPop ( Parse_StackFn_t * p ); extern void Parse_StackFnFree ( Parse_StackFn_t * p ); extern Parse_StackOp_t * Parse_StackOpStart ( int nDepth ); @@ -67,8 +67,7 @@ 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 /// //////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/bdd/parse/parseStack.c b/src/bdd/parse/parseStack.c index cd7cd7e3..8329070e 100644 --- a/src/bdd/parse/parseStack.c +++ b/src/bdd/parse/parseStack.c @@ -24,7 +24,7 @@ struct ParseStackFnStruct { - void ** pData; // the array of elements + DdNode ** pData; // the array of elements int Top; // the index int Size; // the stack size }; @@ -37,7 +37,7 @@ struct ParseStackOpStruct }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -56,7 +56,7 @@ 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->pData = ALLOC( DdNode *, nDepth ); p->Size = nDepth; return p; } @@ -88,7 +88,7 @@ bool Parse_StackFnIsEmpty( Parse_StackFn_t * p ) SeeAlso [] ***********************************************************************/ -void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc ) +void Parse_StackFnPush( Parse_StackFn_t * p, DdNode * bFunc ) { if ( p->Top >= p->Size ) { @@ -109,7 +109,7 @@ void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc ) SeeAlso [] ***********************************************************************/ -void * Parse_StackFnPop( Parse_StackFn_t * p ) +DdNode * Parse_StackFnPop( Parse_StackFn_t * p ) { if ( p->Top == 0 ) { diff --git a/src/bdd/reo/module.make b/src/bdd/reo/module.make index 3a636980..7eb41e0e 100644 --- a/src/bdd/reo/module.make +++ b/src/bdd/reo/module.make @@ -1,7 +1,6 @@ SRC += src/bdd/reo/reoApi.c \ src/bdd/reo/reoCore.c \ src/bdd/reo/reoProfile.c \ - src/bdd/reo/reoShuffle.c \ src/bdd/reo/reoSift.c \ src/bdd/reo/reoSwap.c \ src/bdd/reo/reoTransfer.c \ diff --git a/src/bdd/reo/reo.h b/src/bdd/reo/reo.h index 1a31242a..7e4be855 100644 --- a/src/bdd/reo/reo.h +++ b/src/bdd/reo/reo.h @@ -19,16 +19,10 @@ #ifndef __REO_H__ #define __REO_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include #include #include "extra.h" -//#pragma warning( disable : 4514 ) - //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -93,9 +87,9 @@ struct _reo_plane 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 + unsigned Arg1; // the first argument + unsigned Arg2; // the second argument + unsigned Arg3; // the second argument }; struct _reo_man @@ -172,8 +166,8 @@ struct _reo_man // 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_Not(u) ((reo_unit *)((long)(u) ^ 01)) +#define Unit_NotCond(u,c) ((reo_unit *)((long)(u) ^ (c))) #define Unit_IsConstant(u) ((int)((u)->lev == REO_CONST_LEVEL)) //////////////////////////////////////////////////////////////////////// @@ -221,12 +215,8 @@ extern DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermut extern int Extra_bddReorderTest( DdManager * dd, DdNode * bF ); extern int Extra_addReorderTest( DdManager * dd, DdNode * aF ); -#ifdef __cplusplus -} -#endif - -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/bdd/reo/reoProfile.c b/src/bdd/reo/reoProfile.c index 84a0bc19..b38575f0 100644 --- a/src/bdd/reo/reoProfile.c +++ b/src/bdd/reo/reoProfile.c @@ -330,7 +330,7 @@ void reoProfileWidthPrint( reo_man * p ) WidthMax = p->pPlanes[i].statsWidth; TotalWidth += p->pPlanes[i].statsWidth; } - assert( p->nWidthCur == TotalWidth ); + assert( p->nWidthCur = TotalWidth ); printf( "WIDTH: " ); printf( "Maximum = %5d. ", WidthMax ); printf( "Total = %7d. ", p->nWidthCur ); diff --git a/src/bdd/reo/reoShuffle.c b/src/bdd/reo/reoShuffle.c deleted file mode 100644 index 8dab67a4..00000000 --- a/src/bdd/reo/reoShuffle.c +++ /dev/null @@ -1,224 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoShuffle.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: reoShuffle.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure is similar to Cudd_ShuffleHeap() and Cudd_bddPermute().] - - Description [The first argument is the REO manager. The 2nd/3d - arguments are the function and its CUDD manager. The last argument - is the permutation to be implemented. 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 (that is, the size of CUDD - manager and the size of REO manager).] - - SideEffects [Note that the resulting BDD is not referenced.] - - SeeAlso [] - -***********************************************************************/ -DdNode * reoShuffle( reo_man * p, DdManager * dd, DdNode * bFunc, int * pPerm, int * pPermInv ) -{ - DdNode * bFuncRes = NULL; - int i, k, v; - - if ( Cudd_IsConstant(bFunc) ) - return bFunc; - - // set the initial parameters - p->dd = dd; - p->nSupp = Cudd_SupportSize( dd, bFunc ); - p->nTops = 1; -// p->nNodesBeg = Cudd_DagSize( bFunc ); - - // set the starting permutation - for ( i = 0; i < p->nSupp; i++ ) - { - p->pOrderInt[i] = i; - p->pMapToPlanes[ dd->invperm[i] ] = i; - p->pMapToDdVarsFinal[i] = dd->invperm[i]; - } - - // 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 - p->pTops[0] = reoTransferNodesToUnits_rec( p, bFunc ); -// assert( p->nNodesBeg == p->nNodesCur ); - - // reorder one variable at a time - for ( i = 0; i < p->nSupp; i++ ) - { - if ( p->pOrderInt[i] == pPerm[i] ) - continue; - // find where is variable number pPerm[i] - for ( k = i + 1; k < p->nSupp; k++ ) - if ( pPerm[i] == p->pOrderInt[k] ) - break; - if ( k == p->nSupp ) - { - printf( "reoShuffle() Error: Cannot find a variable.\n" ); - goto finish; - } - // move the variable up - for ( v = k - 1; v >= i; v-- ) - { - reoReorderSwapAdjacentVars( p, v, 1 ); - // check if the number of nodes is not too large - if ( p->nNodesCur > 10000 ) - { - printf( "reoShuffle() Error: BDD size is too large.\n" ); - goto finish; - } - } - assert( p->pOrderInt[i] == pPerm[i] ); - } - - // set the initial parameters - p->nRefNodes = 0; - p->nNodesCur = 0; - p->Signature++; - // transfer the BDDs from REO's internal data structure to CUDD - bFuncRes = reoTransferUnitsToNodes_rec( p, p->pTops[0] ); Cudd_Ref( bFuncRes ); - // 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 -// assert( reoRecursiveDeref( p->pTops[0] ) ); -// assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); - - // perform verification - if ( p->fVerify ) - { - DdNode * bFuncPerm; - bFuncPerm = Cudd_bddPermute( dd, bFunc, pPermInv ); Cudd_Ref( bFuncPerm ); - if ( bFuncPerm != bFuncRes ) - { - printf( "REO: Internal verification has failed!\n" ); - fflush( stdout ); - } - Cudd_RecursiveDeref( dd, bFuncPerm ); - } - - // recycle the data structure - for ( i = 0; i <= p->nSupp; i++ ) - reoUnitsRecycleUnitList( p, p->pPlanes + i ); - -finish : - if ( bFuncRes ) - Cudd_Deref( bFuncRes ); - return bFuncRes; -} - - - -/**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_ShuffleTest( reo_man * pReo, DdManager * dd, DdNode * Func ) -{ -// extern int runtime1, runtime2; - - DdNode * Temp, * bRemap; - int nSuppSize, OffSet, Num, i, clk; - int pOrder[1000], pOrderInv[1000]; - assert( dd->size < 1000 ); - - srand( 0x12341234 ); - nSuppSize = Cudd_SupportSize( dd, Func ); - if ( nSuppSize < 2 ) - return; - - for ( i = 0; i < nSuppSize; i++ ) - pOrder[i] = i; - for ( i = 0; i < 120; i++ ) - { - OffSet = rand() % (nSuppSize - 1); - Num = pOrder[OffSet]; - pOrder[OffSet] = pOrder[OffSet+1]; - pOrder[OffSet+1] = Num; - } - for ( i = 0; i < nSuppSize; i++ ) - pOrderInv[pOrder[i]] = i; - -/* - printf( "Permutation: " ); - for ( i = 0; i < nSuppSize; i++ ) - printf( "%d ", pOrder[i] ); - printf( "\n" ); - printf( "Inverse permutation: " ); - for ( i = 0; i < nSuppSize; i++ ) - printf( "%d ", pOrderInv[i] ); - printf( "\n" ); -*/ - - // create permutation -// Extra_ReorderSetVerification( pReo, 1 ); - bRemap = Extra_bddRemapUp( dd, Func ); Cudd_Ref( bRemap ); - -clk = clock(); - Temp = reoShuffle( pReo, dd, bRemap, pOrder, pOrderInv ); Cudd_Ref( Temp ); -//runtime1 += clock() - clk; - -//printf( "Initial = %d. Final = %d.\n", Cudd_DagSize(bRemap), Cudd_DagSize(Temp) ); - - { - DdNode * bFuncPerm; -clk = clock(); - bFuncPerm = Cudd_bddPermute( dd, bRemap, pOrderInv ); Cudd_Ref( bFuncPerm ); -//runtime2 += clock() - clk; - if ( bFuncPerm != Temp ) - { - printf( "REO: Internal verification has failed!\n" ); - fflush( stdout ); - } - Cudd_RecursiveDeref( dd, bFuncPerm ); - } - - Cudd_RecursiveDeref( dd, Temp ); - Cudd_RecursiveDeref( dd, bRemap ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoSwap.c b/src/bdd/reo/reoSwap.c index 4afa650c..cb730d8e 100644 --- a/src/bdd/reo/reoSwap.c +++ b/src/bdd/reo/reoSwap.c @@ -271,9 +271,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) 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; + p->HTable[HKey].Arg1 = (unsigned)pUnitE; + p->HTable[HKey].Arg2 = (unsigned)pUnitT; + p->HTable[HKey].Arg3 = (unsigned)pUnit; nNodesUpMovedDown++; @@ -512,10 +512,10 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) 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 ) + if ( p->HTable[HKey].Arg1 == (unsigned)pNew1E && p->HTable[HKey].Arg2 == (unsigned)pNew1T ) { // the entry is present // assign this entry - pNewPlane20 = p->HTable[HKey].Arg3; + pNewPlane20 = (reo_unit *)p->HTable[HKey].Arg3; assert( pNewPlane20->lev == lev1 ); fFound = 1; p->HashSuccess++; @@ -549,9 +549,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) // 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; + p->HTable[HKey].Arg1 = (unsigned)pNew1E; + p->HTable[HKey].Arg2 = (unsigned)pNew1T; + p->HTable[HKey].Arg3 = (unsigned)pNewPlane20; nNodesUnrefAdded++; @@ -637,10 +637,10 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) 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 ) + if ( p->HTable[HKey].Arg1 == (unsigned)pNew2E && p->HTable[HKey].Arg2 == (unsigned)pNew2T ) { // the entry is present // assign this entry - pNewPlane21 = p->HTable[HKey].Arg3; + pNewPlane21 = (reo_unit *)p->HTable[HKey].Arg3; assert( pNewPlane21->lev == lev1 ); fFound = 1; p->HashSuccess++; @@ -675,9 +675,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) // 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; + p->HTable[HKey].Arg1 = (unsigned)pNew2E; + p->HTable[HKey].Arg2 = (unsigned)pNew2T; + p->HTable[HKey].Arg3 = (unsigned)pNewPlane21; nNodesUnrefAdded++; diff --git a/src/bdd/reo/reoTransfer.c b/src/bdd/reo/reoTransfer.c index 65d31d01..752cd3d7 100644 --- a/src/bdd/reo/reoTransfer.c +++ b/src/bdd/reo/reoTransfer.c @@ -51,9 +51,9 @@ reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ) { // 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 ) + if ( p->HTable[HKey].Arg1 == (unsigned)F ) { - pUnit = p->HTable[HKey].Arg2; + pUnit = (reo_unit*) p->HTable[HKey].Arg2; assert( pUnit ); // increment the edge counter pUnit->n++; @@ -93,8 +93,8 @@ reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ) // 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; + p->HTable[HKey].Arg1 = (unsigned)F; + p->HTable[HKey].Arg2 = (unsigned)pUnit; } // increment the counter of nodes @@ -126,7 +126,7 @@ DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) 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 ) + if ( p->HTable[HKey].Arg1 == (unsigned)pUnit ) { bRes = (DdNode*) p->HTable[HKey].Arg2; assert( bRes ); @@ -179,8 +179,8 @@ DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) // 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; + p->HTable[HKey].Arg1 = (unsigned)pUnit; + p->HTable[HKey].Arg2 = (unsigned)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 ); diff --git a/src/generic.c b/src/generic.c index f94c50e6..43dd32d8 100644 --- a/src/generic.c +++ b/src/generic.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/generic.h b/src/generic.h index e17d2edf..860f2465 100644 --- a/src/generic.h +++ b/src/generic.h @@ -21,10 +21,6 @@ #ifndef __zzz_H__ #define __zzz_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -38,7 +34,7 @@ extern "C" { //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -46,14 +42,10 @@ extern "C" { //////////////////////////////////////////////////////////////////////// /*=== zzz.c ==========================================================*/ - -#ifdef __cplusplus -} -#endif - -#endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/map/fpga/fpga.c b/src/map/fpga/fpga.c index 40423f4f..3d2ca913 100644 --- a/src/map/fpga/fpga.c +++ b/src/map/fpga/fpga.c @@ -39,7 +39,7 @@ static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) */ //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -56,11 +56,8 @@ static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) 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}} }; - + //Fpga_LutLib_t s_LutLib = { "lutlib", 6, {0,1,2,4,8,16,32}, {0,1,2,3,4,5,6} }; + Fpga_LutLib_t s_LutLib = { "lutlib", 5, {0,1,1,1,1,1}, {0,1,1,1,1,1} }; Abc_FrameSetLibLut( Fpga_LutLibDup(&s_LutLib) ); Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut", Fpga_CommandReadLibrary, 0 ); @@ -80,7 +77,7 @@ void Fpga_Init( Abc_Frame_t * pAbc ) ***********************************************************************/ void Fpga_End() { - Fpga_LutLibFree( Abc_FrameReadLibLut() ); + Fpga_LutLibFree( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) ); } @@ -105,14 +102,14 @@ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) int fVerbose; int c; - pNet = Abc_FrameReadNtk(pAbc); + pNet = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "vh")) != EOF ) { switch (c) { @@ -128,13 +125,13 @@ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != globalUtilOptind + 1 ) + if ( argc != util_optind + 1 ) { goto usage; } // get the input file name - FileName = argv[globalUtilOptind]; + FileName = argv[util_optind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); @@ -195,14 +192,14 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) int fVerbose; int c; - pNet = Abc_FrameReadNtk(pAbc); + pNet = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "vh")) != EOF ) { switch (c) { @@ -218,13 +215,13 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != globalUtilOptind ) + if ( argc != util_optind ) { goto usage; } // set the new network - Fpga_LutLibPrint( Abc_FrameReadLibLut() ); + Fpga_LutLibPrint( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) ); return 0; usage: @@ -235,47 +232,6 @@ usage: 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 index 708cf385..19241a74 100644 --- a/src/map/fpga/fpga.h +++ b/src/map/fpga/fpga.h @@ -19,10 +19,6 @@ #ifndef __FPGA_H__ #define __FPGA_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -32,7 +28,7 @@ extern "C" { //////////////////////////////////////////////////////////////////////// // the maximum size of LUTs used for mapping -#define FPGA_MAX_LUTSIZE 32 +#define FPGA_MAX_LUTSIZE 10 //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// @@ -49,20 +45,20 @@ typedef struct Fpga_LutLibStruct_t_ Fpga_LutLib_t; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// -#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_IsComplement(p) (((int)((long) (p) & 01))) +#define Fpga_Regular(p) ((Fpga_Node_t *)((unsigned)(p) & ~01)) +#define Fpga_Not(p) ((Fpga_Node_t *)((long)(p) ^ 01)) +#define Fpga_NotCond(p,c) ((Fpga_Node_t *)((long)(p) ^ (c))) #define Fpga_Ref(p) #define Fpga_Deref(p) #define Fpga_RecursiveDeref(p,c) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== fpgaCreate.c =============================================================*/ @@ -78,9 +74,7 @@ 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 int Fpga_ManReadVarMax( Fpga_Man_t * p ); extern float * Fpga_ManReadLutAreas( Fpga_Man_t * p ); -extern Fpga_NodeVec_t* Fpga_ManReadMapping( 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 ); @@ -98,16 +92,13 @@ extern void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNode 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 ); @@ -143,33 +134,23 @@ 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 ); -extern void Fpga_CutsCleanRoot( 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 ); +/*=== fpgaFraig.c =============================================================*/ +extern Fpga_Man_t * Fpga_ManDupFraig( Fraig_Man_t * pManFraig ); +extern Fpga_Man_t * Fpga_ManBalanceFraig( Fraig_Man_t * pManFraig, int * pInputArrivals ); /*=== 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 /// //////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/map/fpga/fpgaCore.c b/src/map/fpga/fpgaCore.c index 634a8eb1..9ca65379 100644 --- a/src/map/fpga/fpgaCore.c +++ b/src/map/fpga/fpgaCore.c @@ -24,12 +24,8 @@ static int Fpga_MappingPostProcess( Fpga_Man_t * p ); -extern int s_MappingTime; -extern int s_MappingMem; - - //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -50,7 +46,7 @@ extern int s_MappingMem; 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 @@ -68,23 +64,19 @@ int Fpga_Mapping( Fpga_Man_t * p ) p->timeMatch = clock() - clk; // perform area recovery - clk = clock(); - if ( !Fpga_MappingPostProcess( p ) ) - return 0; - p->timeRecover = clock() - clk; + if ( p->fAreaRecovery ) + { + 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 ); - } + Fpga_MappingPrintOutputArrivals( p ); return 1; } @@ -96,7 +88,7 @@ int Fpga_Mapping( Fpga_Man_t * p ) 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.] + minimization in LUT-based FGPA technology mapping. Proc. IWLS '04.] SideEffects [] @@ -105,15 +97,12 @@ int Fpga_Mapping( Fpga_Man_t * p ) ***********************************************************************/ int Fpga_MappingPostProcess( Fpga_Man_t * p ) { - int fShowSwitching = 0; + int fShowSwitching = 1; 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 ); @@ -122,20 +111,14 @@ 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 ); + Fpga_TimeComputeRequiredGlobal( p ); // remap topologically Fpga_MappingMatches( p, 0 ); // get the resulting area @@ -148,8 +131,6 @@ 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 ); } } @@ -162,7 +143,7 @@ PRT( "Time", clock() - clk ); { clk = clock(); // compute the required times and the fanouts - Fpga_TimeComputeRequiredGlobal( p, 0 ); + Fpga_TimeComputeRequiredGlobal( p ); // remap topologically if ( p->fSwitching ) Fpga_MappingMatchesSwitch( p ); @@ -175,8 +156,6 @@ 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 ); } } diff --git a/src/map/fpga/fpgaCreate.c b/src/map/fpga/fpgaCreate.c index be71d74e..b7bfa3c5 100644 --- a/src/map/fpga/fpgaCreate.c +++ b/src/map/fpga/fpgaCreate.c @@ -31,7 +31,7 @@ static Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -52,9 +52,7 @@ Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ) { retu 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; } -int Fpga_ManReadVarMax( Fpga_Man_t * p ) { return p->pLutLib->LutMax; } float * Fpga_ManReadLutAreas( Fpga_Man_t * p ) { return p->pLutLib->pLutAreas; } -Fpga_NodeVec_t* Fpga_ManReadMapping( Fpga_Man_t * p ) { return p->vMapping; } 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; } @@ -68,9 +66,7 @@ void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p 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************************************************************* @@ -99,7 +95,6 @@ int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ) { return pLib->LutMa ***********************************************************************/ 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; } @@ -169,7 +164,7 @@ Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose ) // start the manager p = ALLOC( Fpga_Man_t, 1 ); memset( p, 0, sizeof(Fpga_Man_t) ); - p->pLutLib = Abc_FrameReadLibLut(); + p->pLutLib = Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()); p->nVarsMax = p->pLutLib->LutMax; p->fVerbose = fVerbose; p->fAreaRecovery = 1; @@ -228,8 +223,8 @@ void Fpga_ManFree( Fpga_Man_t * p ) Fpga_NodeVecFree( p->vAnds ); if ( p->vNodesAll ) Fpga_NodeVecFree( p->vNodesAll ); - Extra_MmFixedStop( p->mmNodes ); - Extra_MmFixedStop( p->mmCuts ); + Extra_MmFixedStop( p->mmNodes, 0 ); + Extra_MmFixedStop( p->mmCuts, 0 ); FREE( p->ppOutputNames ); FREE( p->pInputArrivals ); FREE( p->pInputs ); diff --git a/src/map/fpga/fpgaCut.c b/src/map/fpga/fpgaCut.c index ce688179..5b5fbe69 100644 --- a/src/map/fpga/fpgaCut.c +++ b/src/map/fpga/fpgaCut.c @@ -35,11 +35,9 @@ struct Fpga_CutTableStrutct_t }; // the largest number of cuts considered -//#define FPGA_CUTS_MAX_COMPUTE 500 -#define FPGA_CUTS_MAX_COMPUTE 2000 +#define FPGA_CUTS_MAX_COMPUTE 500 // the largest number of cuts used -//#define FPGA_CUTS_MAX_USE 200 -#define FPGA_CUTS_MAX_USE 1000 +#define FPGA_CUTS_MAX_USE 200 // primes used to compute the hash key static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; @@ -97,7 +95,7 @@ static Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -130,10 +128,9 @@ void Fpga_MappingCuts( Fpga_Man_t * p ) 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 ); + assert( p->nVarsMax > 1 && p->nVarsMax < 7 ); Fpga_MappingCreatePiCuts( p ); // compute the cuts for the internal nodes @@ -155,9 +152,8 @@ void Fpga_MappingCuts( Fpga_Man_t * p ) if ( p->fVerbose ) { nCuts = Fpga_CutCountAll(p); - printf( "Nodes = %6d. Total %d-cuts = %d. Cuts per node = %.1f. ", + printf( "Nodes = %6d. Total %d-feasible cuts = %d. Cuts per node = %.1f.\n", p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); - PRT( "Time", clock() - clk ); } // print the cuts for the first primary output @@ -249,7 +245,7 @@ Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Nod // set at the node pNode->pCuts = pCut; // remove the dominated cuts -// Fpga_CutFilter( p, pNode ); + Fpga_CutFilter( p, pNode ); // set the phase correctly if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) ) { @@ -351,8 +347,8 @@ void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ) 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_Node_t * ppNodes[6]; + Fpga_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL }; Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; int nNodes, Counter, i; Fpga_Cut_t ** ppArray1, ** ppArray2, ** ppArray3; @@ -536,8 +532,8 @@ QUITS : 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_Node_t * ppNodes[6]; + Fpga_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL }; Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; int nNodes, Counter, i; @@ -686,8 +682,7 @@ int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNo { 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 ) + if ( ppNodes[k] < ppNodes[min] ) min = k; pNodeTemp = ppNodes[i]; ppNodes[i] = ppNodes[min]; @@ -772,10 +767,7 @@ int Fpga_CutCountAll( Fpga_Man_t * pMan ) 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; } @@ -802,28 +794,6 @@ void Fpga_CutsCleanSign( Fpga_Man_t * pMan ) pCut->uSign = 0; } -/**Function************************************************************* - - Synopsis [Clean the signatures.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutsCleanRoot( 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->pRoot = NULL; -} - /**Function************************************************************* @@ -1109,7 +1079,7 @@ Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_ nCuts = Fpga_CutList2Array( p->pCuts1, pList ); assert( nCuts <= FPGA_CUTS_MAX_COMPUTE ); // sort the cuts - qsort( (void *)p->pCuts1, nCuts, sizeof(void *), + qsort( (void *)p->pCuts1, nCuts, sizeof(Fpga_Cut_t *), (int (*)(const void *, const void *)) Fpga_CutSortCutsCompare ); // move them back into the list if ( nCuts > FPGA_CUTS_MAX_USE - 1 ) diff --git a/src/map/fpga/fpgaCutUtils.c b/src/map/fpga/fpgaCutUtils.c index e60a1dee..2419cac4 100644 --- a/src/map/fpga/fpgaCutUtils.c +++ b/src/map/fpga/fpgaCutUtils.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -290,9 +290,7 @@ void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) // 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]; + pCut->tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves]; } @@ -340,7 +338,7 @@ float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) return 0; aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); - assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); + assert( aResult == aResult2 ); return aResult; } @@ -362,7 +360,7 @@ float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) return 0; aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); - assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); + assert( aResult == aResult2 ); return aResult; } diff --git a/src/map/fpga/fpgaFanout.c b/src/map/fpga/fpgaFanout.c index c28a8799..0a34ff43 100644 --- a/src/map/fpga/fpgaFanout.c +++ b/src/map/fpga/fpgaFanout.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/fpga/fpgaGENERIC.c b/src/map/fpga/fpgaGENERIC.c index 4483c215..f272c1b8 100644 --- a/src/map/fpga/fpgaGENERIC.c +++ b/src/map/fpga/fpgaGENERIC.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/fpga/fpgaInt.h b/src/map/fpga/fpgaInt.h index c01d1e3d..ec6057a7 100644 --- a/src/map/fpga/fpgaInt.h +++ b/src/map/fpga/fpgaInt.h @@ -28,6 +28,7 @@ #include #include #include "extra.h" +#include "fraig.h" #include "fpga.h" //////////////////////////////////////////////////////////////////////// @@ -38,7 +39,7 @@ //#define FPGA_ALLOCATE_FANOUT 1 //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef _WIN32 @@ -67,16 +68,16 @@ #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))) +#define Fpga_CutIsComplement(p) (((int)((long) (p) & 01))) +#define Fpga_CutRegular(p) ((Fpga_Cut_t *)((unsigned)(p) & ~01)) +#define Fpga_CutNot(p) ((Fpga_Cut_t *)((long)(p) ^ 01)) +#define Fpga_CutNotCond(p,c) ((Fpga_Cut_t *)((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))) +#define Fpga_SeqIsComplement( p ) (((int)((long) (p) & 01))) +#define Fpga_SeqRegular( p ) ((Fpga_Node_t *)((unsigned)(p) & ~015)) +#define Fpga_SeqIndex( p ) ((((unsigned)(p)) >> 1) & 07) +#define Fpga_SeqIndexCreate( p, Ind ) (((unsigned)(p)) | (1 << (((unsigned)(Ind)) & 07))) // internal macros for referencing of nodes #define Fpga_NodeReadRef(p) ((Fpga_Regular(p))->nRefs) @@ -122,9 +123,7 @@ struct Fpga_ManStruct_t_ 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 + int nTravIds; // support of choice nodes int nChoiceNodes; // the number of choice nodes @@ -171,9 +170,8 @@ 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 + float pLutDelays[FPGA_MAX_LUTSIZE+1];// the delays of LUTs }; // the mapping node @@ -184,8 +182,8 @@ struct Fpga_NodeStruct_t_ 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 - int Num2; // the temporary number of this node - int nRefs; // the number of references (fanouts) of the given 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 @@ -278,16 +276,12 @@ struct Fpga_NodeVecStruct_t_ 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 /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== fpgaCut.c ===============================================================*/ @@ -337,7 +331,7 @@ extern float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeV 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_TimeComputeRequiredGlobal( Fpga_Man_t * p ); 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 ); @@ -381,8 +375,8 @@ extern void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ); /*=== CUDD package.c ===============================================================*/ extern unsigned int Cudd_Prime( unsigned int p ); -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/map/fpga/fpgaLib.c b/src/map/fpga/fpgaLib.c index b1bb4cdc..9fd8e281 100644 --- a/src/map/fpga/fpgaLib.c +++ b/src/map/fpga/fpgaLib.c @@ -23,24 +23,9 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// -/**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.] @@ -57,7 +42,7 @@ Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose ) char pBuffer[1000], * pToken; Fpga_LutLib_t * p; FILE * pFile; - int i, k; + int i; pFile = fopen( FileName, "r" ); if ( pFile == NULL ) @@ -68,7 +53,7 @@ Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose ) p = ALLOC( Fpga_LutLib_t, 1 ); memset( p, 0, sizeof(Fpga_LutLib_t) ); - p->pName = Extra_UtilStrsav( FileName ); + p->pName = util_strsav( FileName ); i = 1; while ( fgets( pBuffer, 1000, pFile ) != NULL ) @@ -85,66 +70,25 @@ Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose ) 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; + pToken = strtok( NULL, " \t\n" ); + p->pLutDelays[i] = (float)atof(pToken); if ( i == FPGA_MAX_LUTSIZE ) { printf( "Skipping LUTs of size more than %d.\n", i ); - return NULL; + break; } i++; } p->LutMax = i-1; - if ( p->LutMax > FPGA_MAX_LEAVES ) { p->LutMax = FPGA_MAX_LEAVES; - printf( "Warning: LUTs with more than %d inputs will not be used.\n", 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; } @@ -164,7 +108,7 @@ 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 ); + pNew->pName = util_strsav( pNew->pName ); return pNew; } @@ -201,22 +145,11 @@ void Fpga_LutLibFree( Fpga_LutLib_t * pLutLib ) ***********************************************************************/ void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib ) { - int i, k; + int i; 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] ); + for ( i = 1; i <= pLutLib->LutMax; i++ ) + printf( "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i] ); } /**Function************************************************************* @@ -236,7 +169,7 @@ int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib ) int i; for ( i = 1; i <= pLutLib->LutMax; i++ ) { - Delay = pLutLib->pLutDelays[i][0]; + Delay = pLutLib->pLutDelays[i]; if ( ((float)((int)Delay)) != Delay ) return 0; } diff --git a/src/map/fpga/fpgaMatch.c b/src/map/fpga/fpgaMatch.c index 73fa1258..20444209 100644 --- a/src/map/fpga/fpgaMatch.c +++ b/src/map/fpga/fpgaMatch.c @@ -30,7 +30,7 @@ static Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * p static int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -87,18 +87,6 @@ int Fpga_MappingMatches( Fpga_Man_t * p, int 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; } @@ -140,7 +128,7 @@ 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) ) + if ( pCut->tArrival > pNode->tRequired ) continue; // if no cut is assigned, use the current one if ( pNode->pCutBest == NULL ) @@ -152,11 +140,11 @@ clk = clock(); // (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) )) || + (pNode->pCutBest->tArrival > pCut->tArrival || + pNode->pCutBest->tArrival == pCut->tArrival && 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->aFlow > pCut->aFlow || + pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival)) ) { pNode->pCutBest = pCut; } @@ -289,7 +277,7 @@ 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 ) ) + if ( pCut->tArrival > pNode->tRequired ) continue; // get the area of this cut pCut->aFlow = Fpga_CutGetAreaDerefed( p, pCut ); @@ -300,8 +288,8 @@ clk = clock(); 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) ) + if ( pNode->pCutBest->aFlow > pCut->aFlow || + pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival ) { pNode->pCutBest = pCut; } @@ -323,7 +311,7 @@ clk = clock(); if ( pNode->nRefs ) { pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); -// assert( pNode->pCutBest->aFlow <= aAreaCutBest ); + assert( pNode->pCutBest->aFlow <= aAreaCutBest ); // assert( pNode->tRequired < FPGA_FLOAT_LARGE ); } return 1; @@ -410,7 +398,7 @@ 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 ) ) + if ( pCut->tArrival > pNode->tRequired ) continue; // get the area of this cut pCut->aFlow = Fpga_CutGetSwitchDerefed( p, pNode, pCut ); @@ -421,8 +409,8 @@ clk = clock(); 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) ) + if ( pNode->pCutBest->aFlow > pCut->aFlow || + pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival ) { pNode->pCutBest = pCut; } @@ -513,7 +501,7 @@ void Fpga_Experiment( Fpga_Man_t * p ) AreaBefore = pNode->pCutBest->aFlow; pNode->pCutBest->aFlow = FPGA_FLOAT_LARGE; - Fpga_TimeComputeRequiredGlobal( p, 0 ); + Fpga_TimeComputeRequiredGlobal( p ); vNodesTfo = Fpga_CollectNodeTfo( p, pNode ); if ( Fpga_MappingMatchesAreaArray( p, vNodesTfo ) == 0 ) diff --git a/src/map/fpga/fpgaSwitch.c b/src/map/fpga/fpgaSwitch.c index 5e881959..8cc77990 100644 --- a/src/map/fpga/fpgaSwitch.c +++ b/src/map/fpga/fpgaSwitch.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**function************************************************************* @@ -139,8 +139,8 @@ float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping ) } // add buffer for each CO driven by a CI for ( i = 0; i < pMan->nOutputs; i++ ) - if ( Fpga_NodeIsVar(Fpga_Regular(pMan->pOutputs[i])) && !Fpga_IsComplement(pMan->pOutputs[i]) ) - Switch += Fpga_Regular(pMan->pOutputs[i])->Switching; + if ( Fpga_NodeIsVar(pMan->pOutputs[i]) && !Fpga_IsComplement(pMan->pOutputs[i]) ) + Switch += pMan->pOutputs[i]->Switching; return Switch; } diff --git a/src/map/fpga/fpgaTime.c b/src/map/fpga/fpgaTime.c index 879cad4d..6cbe16f9 100644 --- a/src/map/fpga/fpgaTime.c +++ b/src/map/fpga/fpgaTime.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -46,7 +46,7 @@ float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) 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]; + tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves]; return tArrival; } @@ -87,34 +87,13 @@ 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 = 0; i < p->nOutputs; i++ ) { - 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 ); + if ( Fpga_NodeIsConst(p->pOutputs[i]) ) + continue; + fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); } return fRequired; } @@ -130,24 +109,9 @@ float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p ) SeeAlso [] ***********************************************************************/ -void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime ) +void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p ) { 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 ); } @@ -169,23 +133,10 @@ void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired ) 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; + 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************************************************************* @@ -216,7 +167,7 @@ void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ) if ( !Fpga_NodeIsAnd(pNode) ) continue; // get the required time for children - fRequired = pNode->tRequired - p->pLutLib->pLutDelays[pNode->pCutBest->nLeaves][0]; + fRequired = pNode->tRequired - p->pLutLib->pLutDelays[pNode->pCutBest->nLeaves]; // update the required time of the children for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) { diff --git a/src/map/fpga/fpgaTruth.c b/src/map/fpga/fpgaTruth.c index e3eb487f..17c6385c 100644 --- a/src/map/fpga/fpgaTruth.c +++ b/src/map/fpga/fpgaTruth.c @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -94,71 +94,12 @@ void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ) 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 index b951fd8f..db0f9623 100644 --- a/src/map/fpga/fpgaUtils.c +++ b/src/map/fpga/fpgaUtils.c @@ -30,11 +30,10 @@ static int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// @@ -51,11 +50,9 @@ static Fpga_Man_t * s_pMan = NULL; ***********************************************************************/ Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ) { - Fpga_NodeVec_t * vNodes;//, * vNodesCo; + Fpga_NodeVec_t * vNodes; 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 @@ -68,15 +65,10 @@ Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ) // 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; } @@ -938,47 +930,6 @@ void Fpga_ManReportChoices( Fpga_Man_t * pMan ) */ } -/**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 index 70a4a7ac..a8c6b983 100644 --- a/src/map/fpga/fpgaVec.c +++ b/src/map/fpga/fpgaVec.c @@ -25,7 +25,7 @@ static int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/if/if.h b/src/map/if/if.h deleted file mode 100644 index b3d2d745..00000000 --- a/src/map/if/if.h +++ /dev/null @@ -1,410 +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" -#include "tim.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 parameters - 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 fEdge; // uses edge-based cut selection heuristics - int fCutMin; // performs cut minimization by removing functionally reducdant variables - 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 * vObjsRev; // reverse topological order of 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 - int nSmallSupp; // the small support - // timing manager - Tim_Man_t * pManTim; -}; - -// 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 - float Edge; // the edge flow - 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 IdPio; // integer ID of PIs/POs - 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 int * If_CutLeaves( If_Cut_t * pCut ) { return pCut->pLeaves; } -static inline unsigned * If_CutTruth( If_Cut_t * pCut ) { return pCut->pTruth; } -static inline unsigned If_CutSuppMask( If_Cut_t * pCut ) { return (~(unsigned)0) >> (32-pCut->nLeaves); } -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 in topological order -#define If_ManForEachObj( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vObjs, pObj, i ) -// iterator over all objects in reverse topological order -#define If_ManForEachObjReverse( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vObjsRev, 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 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_CutPrint( If_Man_t * p, If_Cut_t * pCut ); -extern void If_CutPrintTiming( If_Man_t * p, 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 float If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut ); -/*=== 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_ManScanMappingDirect( 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 ); - -extern Vec_Ptr_t * If_ManReverseOrder( If_Man_t * p ); -extern void If_ManMarkMapping( If_Man_t * p ); -extern Vec_Ptr_t * If_ManCollectMappingDirect( 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 f7124703..00000000 --- a/src/map/if/ifCore.c +++ /dev/null @@ -1,148 +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) ); - // derive reverse top order - p->vObjsRev = If_ManReverseOrder( p ); - - // try sequential mapping - if ( p->pPars->fSeqMap ) - { - int RetValue = 1; - 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 cc842c19..00000000 --- a/src/map/if/ifCut.c +++ /dev/null @@ -1,988 +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_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) -{ - If_Cut_t * pC0 = *ppC0; - If_Cut_t * pC1 = *ppC1; - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Prepares the object for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutCompareDelayOld( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) -{ - If_Cut_t * pC0 = *ppC0; - If_Cut_t * pC1 = *ppC1; - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - 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_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) -{ - If_Cut_t * pC0 = *ppC0; - If_Cut_t * pC1 = *ppC1; - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - 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 - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - 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 - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - return 1; - if ( pC0->Edge < pC1->Edge - p->fEpsilon ) - return -1; - if ( pC0->Edge > pC1->Edge + p->fEpsilon ) - 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 - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - return 0; - } - if ( p->SortMode == 0 ) // delay - { - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - return 1; - if ( pC0->Edge < pC1->Edge - p->fEpsilon ) - return -1; - if ( pC0->Edge > pC1->Edge + p->fEpsilon ) - return 1; - return 0; - } - assert( p->SortMode == 2 ); // delay old - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - return 1; - if ( pC0->Edge < pC1->Edge - p->fEpsilon ) - return -1; - if ( pC0->Edge > pC1->Edge + p->fEpsilon ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparison function for two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int If_ManSortCompare_old( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 ) -{ - if ( p->SortMode == 1 ) // area - { - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - 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 - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - return 0; - } - if ( p->SortMode == 0 ) // delay - { - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - return 1; - return 0; - } - assert( p->SortMode == 2 ); // delay old - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - 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 [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 [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; -} - - -/**Function************************************************************* - - Synopsis [Computes area flow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutAreaFlow( 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 [Computes area flow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut ) -{ - If_Obj_t * pLeaf; - float Flow; - int i; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - Flow = pCut->nLeaves; - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - if ( pLeaf->nRefs == 0 ) - Flow += If_ObjCutBest(pLeaf)->Edge; - else if ( p->pPars->fSeqMap ) // seq - Flow += If_ObjCutBest(pLeaf)->Edge / pLeaf->nRefs; - else - { - assert( pLeaf->EstRefs > p->fEpsilon ); - Flow += If_ObjCutBest(pLeaf)->Edge / 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_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut ) -{ - 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) ) - continue; - Area += If_CutAreaDeref( p, If_ObjCutBest(pLeaf) ); - } - return Area; -} - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut ) -{ - 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) ) - continue; - Area += If_CutAreaRef( p, If_ObjCutBest(pLeaf) ); - } - return Area; -} - -/**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 ) -{ - float aResult, aResult2; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - aResult2 = If_CutAreaRef( p, pCut ); - aResult = If_CutAreaDeref( p, pCut ); - 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 ) -{ - float aResult, aResult2; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - aResult2 = If_CutAreaDeref( p, pCut ); - aResult = If_CutAreaRef( p, pCut ); - 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_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut ) -{ - If_Obj_t * pLeaf; - float Edge; - int i; - Edge = pCut->nLeaves; - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - assert( pLeaf->nRefs > 0 ); - if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) ) - continue; - Edge += If_CutEdgeDeref( p, If_ObjCutBest(pLeaf) ); - } - return Edge; -} - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut ) -{ - If_Obj_t * pLeaf; - float Edge; - int i; - Edge = pCut->nLeaves; - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - assert( pLeaf->nRefs >= 0 ); - if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) ) - continue; - Edge += If_CutEdgeRef( p, If_ObjCutBest(pLeaf) ); - } - return Edge; -} - -/**Function************************************************************* - - Synopsis [Computes edge of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut ) -{ - float aResult, aResult2; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - aResult2 = If_CutEdgeRef( p, pCut ); - aResult = If_CutEdgeDeref( p, pCut ); - 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_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut ) -{ - float aResult, aResult2; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - aResult2 = If_CutEdgeDeref( p, pCut ); - aResult = If_CutEdgeRef( p, pCut ); - assert( aResult > aResult2 - p->fEpsilon ); - assert( aResult < aResult2 + p->fEpsilon ); - return aResult; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c deleted file mode 100644 index 6b21919b..00000000 --- a/src/map/if/ifMan.c +++ /dev/null @@ -1,577 +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( "K = %d. Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d.\n", - p->pPars->nLutSize, 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 ) -{ -// printf( "Small support = %d.\n", p->nSmallSupp ); - Vec_PtrFree( p->vCis ); - Vec_PtrFree( p->vCos ); - Vec_PtrFree( p->vObjs ); -// Vec_PtrFree( p->vMapped ); - Vec_PtrFree( p->vTemp ); - if ( p->vObjsRev ) Vec_PtrFree( p->vObjsRev ); - 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 ); - if ( p->pManTim ) - Tim_ManStop( p->pManTim ); - 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; - pObj->IdPio = Vec_PtrSize( p->vCis ); - 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 ); - pObj->IdPio = Vec_PtrSize( p->vCos ); - Vec_PtrPush( p->vCos, pObj ); - pObj->Type = IF_CO; - pObj->fCompl0 = If_IsComplement(pDriver); pDriver = If_Regular(pDriver); - pObj->pFanin0 = pDriver; pDriver->nRefs++; - pObj->Level = pDriver->Level; - 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 1ac5ef21..00000000 --- a/src/map/if/ifMap.c +++ /dev/null @@ -1,350 +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_CutAreaDeref( p, If_ObjCutBest(pObj) ); - - // 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_CutAreaFlow( p, pCut ); - if ( p->pPars->fEdge ) - pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( 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_CutAreaFlow( p, pCut ); - if ( p->pPars->fEdge ) - pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( 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_CutAreaRef( p, If_ObjCutBest(pObj) ); - - // 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_CutAreaDeref( p, If_ObjCutBest(pObj) ); - - // 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_CutAreaFlow( p, pCut ); - if ( p->pPars->fEdge ) - pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( 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_CutAreaRef( p, If_ObjCutBest(pObj) ); - - // 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(); - float arrTime; - 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; - // make sure the visit counters are all zero - If_ManForEachNode( p, pObj, i ) - assert( pObj->nVisits == pObj->nVisitsCopy ); - // map the internal nodes - if ( p->pManTim != NULL ) - { - Tim_ManIncrementTravId( p->pManTim ); - If_ManForEachObj( p, pObj, i ) - { - if ( If_ObjIsAnd(pObj) ) - { - If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess ); - if ( pObj->fRepr ) - If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess ); - } - else if ( If_ObjIsCi(pObj) ) - { - arrTime = Tim_ManGetPiArrival( p->pManTim, pObj->IdPio ); - If_ObjSetArrTime( pObj, arrTime ); -/* - if ( pObj->IdPio >= 2000 ) - { - int x = 0; - printf( "+%d %6.3f ", pObj->IdPio, arrTime ); - } -*/ - } - else if ( If_ObjIsCo(pObj) ) - { - arrTime = If_ObjArrTime( If_ObjFanin0(pObj) ); - Tim_ManSetPoArrival( p->pManTim, pObj->IdPio, arrTime ); - } - else if ( If_ObjIsConst1(pObj) ) - { - } - else - assert( 0 ); - } -// Tim_ManPrint( p->pManTim ); - } - else - { - // 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 ); -// Tim_ManPrint( p->pManTim ); - 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/src/map/if/ifReduce.c b/src/map/if/ifReduce.c deleted file mode 100644 index 0912a965..00000000 --- a/src/map/if/ifReduce.c +++ /dev/null @@ -1,575 +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. 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); - pCut->Delay = If_CutDelay( p, pCut ); - 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 ( AreaBef == 1 ) -// return; - // the cut is non-trivial - If_ManImproveNodePrepare( p, pObj, nLimit, vFront, vFrontOld, vVisited ); - // iteratively modify the cut - If_CutAreaDeref( p, pCut ); - CostBef = If_ManImproveCutCost( p, vFront ); - If_ManImproveNodeFaninCompact( p, pObj, nLimit, vFront, vVisited ); - CostAft = If_ManImproveCutCost( p, vFront ); - If_CutAreaRef( p, pCut ); - 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 ( AreaAft > AreaBef || pCut->Delay > pObj->Required + p->fEpsilon ) - { - If_ManImproveNodeUpdate( p, pObj, vFrontOld ); - AreaAft = If_CutAreaRefed( p, pCut ); - 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_CutAreaDeref( p, pCut ); - // 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_CutAreaRef( p, pCut ); -} - - -/**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_CutAreaDeref( p, pCut ); - // get the area - AreaBef = If_CutAreaDerefed( p, pCut ); - // 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 ); - // 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 ); -*/ -} - -/**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 3d1dab1b..00000000 --- a/src/map/if/ifTime.c +++ /dev/null @@ -1,228 +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 ) - { -/* - if ( pLeaf->IdPio > 2000 ) - { - int x = 0; - printf( "-%d %6.3f ", pLeaf->IdPio, If_ObjCutBest(pLeaf)->Delay ); - } -*/ - 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 f18d8308..00000000 --- a/src/map/if/ifTruth.c +++ /dev/null @@ -1,404 +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 /// -//////////////////////////////////////////////////////////////////////// - -static int If_CutTruthMinimize( If_Man_t * p, If_Cut_t * pCut ); - -//////////////////////////////////////////////////////////////////////// -/// 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 [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 If_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-- ) - { - If_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) ) - If_TruthCopy( pOut, pIn, nVarsAll ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if TT depends on the given variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutTruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = If_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 support of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned If_CutTruthSupport( unsigned * pTruth, int nVars, int * pnSuppSize ) -{ - int i, Support = 0; - int nSuppSize = 0; - for ( i = 0; i < nVars; i++ ) - if ( If_CutTruthVarInSupport( pTruth, nVars, i ) ) - { - Support |= (1 << i); - nSuppSize++; - } - *pnSuppSize = nSuppSize; - return Support; -} - - -/**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 If_CutFactorTest( 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 ); - - // minimize the support of the cut - if ( p->pPars->fCutMin ) - If_CutTruthMinimize( p, pCut ); - - // perform -// If_CutFactorTest( If_CutTruth(pCut), pCut->nLimit ); -// printf( "%d ", If_CutLeaveNum(pCut) - If_CutTruthSupportSize(If_CutTruth(pCut), If_CutLeaveNum(pCut)) ); -} - - -/**Function************************************************************* - - Synopsis [Minimize support of the cut.] - - Description [Returns 1 if the node's support has changed] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutTruthMinimize( If_Man_t * p, If_Cut_t * pCut ) -{ - unsigned uSupport; - int nSuppSize, i, k; - // compute the support of the cut's function - uSupport = If_CutTruthSupport( If_CutTruth(pCut), If_CutLeaveNum(pCut), &nSuppSize ); - if ( nSuppSize == If_CutLeaveNum(pCut) ) - return 0; - -// TEMPORARY - if ( nSuppSize < 2 ) - { - p->nSmallSupp++; - return 0; - } -// if ( If_CutLeaveNum(pCut) - nSuppSize > 1 ) -// return 0; -//printf( "%d %d ", If_CutLeaveNum(pCut), nSuppSize ); - - // shrink the truth table - If_TruthShrink( p->puTemp[0], If_CutTruth(pCut), nSuppSize, pCut->nLimit, uSupport, 1 ); - // update leaves and signature - pCut->uSign = 0; - for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ ) - { - if ( !(uSupport & (1 << i)) ) - continue; - pCut->pLeaves[k++] = pCut->pLeaves[i]; - pCut->uSign |= If_ObjCutSign( pCut->pLeaves[i] ); - } - assert( k == nSuppSize ); - pCut->nLeaves = nSuppSize; - // verify the result -// uSupport = If_CutTruthSupport( If_CutTruth(pCut), If_CutLeaveNum(pCut), &nSuppSize ); -// assert( nSuppSize == If_CutLeaveNum(pCut) ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifUtil.c b/src/map/if/ifUtil.c deleted file mode 100644 index 2624efd0..00000000 --- a/src/map/if/ifUtil.c +++ /dev/null @@ -1,658 +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; - float reqTime; - - // compute area, clean required times, collect nodes used in the mapping -// p->AreaGlo = If_ManScanMapping( p ); - If_ManMarkMapping( p ); - - if ( p->pManTim == NULL ) - { - // 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 ); - If_ManForEachObjReverse( p, pObj, i ) - { - if ( pObj->nRefs == 0 ) - continue; - If_CutPropagateRequired( p, If_ObjCutBest(pObj), pObj->Required ); - } - } - else - { - // get the global required times - p->RequiredGlo = If_ManDelayMax( p, 0 ); - // do not propagate required times if area minimization is requested - if ( p->pPars->fAreaOnly ) - return; - // set the required times for the POs - Tim_ManIncrementTravId( p->pManTim ); - if ( p->pPars->fLatchPaths ) - { - assert( 0 ); - If_ManForEachPo( p, pObj, i ) - Tim_ManSetPoRequired( p->pManTim, pObj->IdPio, IF_FLOAT_LARGE ); - If_ManForEachLatchInput( p, pObj, i ) - Tim_ManSetPoRequired( p->pManTim, pObj->IdPio, p->RequiredGlo ); - } - else - { - Tim_ManSetPoRequiredAll( p->pManTim, p->RequiredGlo ); -// If_ManForEachCo( p, pObj, i ) -// Tim_ManSetPoRequired( p->pManTim, pObj->IdPio, p->RequiredGlo ); - } - // go through the nodes in the reverse topological order - If_ManForEachObjReverse( p, pObj, i ) - { - if ( If_ObjIsAnd(pObj) ) - { - if ( pObj->nRefs == 0 ) - continue; - If_CutPropagateRequired( p, If_ObjCutBest(pObj), pObj->Required ); - } - else if ( If_ObjIsCi(pObj) ) - { - reqTime = pObj->Required; - Tim_ManSetPiRequired( p->pManTim, pObj->IdPio, reqTime ); - } - else if ( If_ObjIsCo(pObj) ) - { - reqTime = Tim_ManGetPoRequired( p->pManTim, pObj->IdPio ); - If_ObjFanin0(pObj)->Required = IF_MIN( reqTime, If_ObjFanin0(pObj)->Required ); - } - else if ( If_ObjIsConst1(pObj) ) - { - } - else // add the node to the mapper - assert( 0 ); - } - } -} - -#if 0 - -/**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 - p->nNets = 0; - 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 [Collects the nodes in reverse topological order in array - p->vMapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_ManScanMappingDirect( 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 ( i = 0; i <= p->nLevelMax; 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; -} - -#endif - -/**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 the reverse topological order of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * If_ManReverseOrder( If_Man_t * p ) -{ - Vec_Ptr_t * vOrder; - If_Obj_t * pObj, ** ppStore; - int i; - // allocate place to store the nodes - ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 ); - memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); - // add the nodes - If_ManForEachObj( p, pObj, i ) - { - assert( pObj->Level >= 0 && pObj->Level <= (unsigned)p->nLevelMax ); - pObj->pCopy = (char *)ppStore[pObj->Level]; - ppStore[pObj->Level] = pObj; - } - vOrder = Vec_PtrAlloc( If_ManObjNum(p) ); - for ( i = p->nLevelMax; i >= 0; i-- ) - for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy ) - Vec_PtrPush( vOrder, pObj ); - free( ppStore ); - // print the order -// Vec_PtrForEachEntry( vOrder, pObj, i ) -// printf( "Obj %2d Type %d Level = %d\n", pObj->Id, pObj->Type, pObj->Level ); - return vOrder; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj ) -{ - 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) ); - // 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_ManMarkMapping_rec( p, pLeaf ); - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManMarkMapping( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i; - If_ManForEachObj( p, pObj, i ) - { - pObj->Required = IF_FLOAT_LARGE; - pObj->nVisits = pObj->nVisitsCopy; - pObj->nRefs = 0; - } - p->nNets = 0; - p->AreaGlo = 0.0; - If_ManForEachCo( p, pObj, i ) - p->AreaGlo += If_ManMarkMapping_rec( p, If_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Collects nodes used in the mapping in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * If_ManCollectMappingDirect( If_Man_t * p ) -{ - Vec_Ptr_t * vOrder; - If_Obj_t * pObj; - int i; - If_ManMarkMapping( p ); - vOrder = Vec_PtrAlloc( If_ManObjNum(p) ); - If_ManForEachObj( p, pObj, i ) - if ( If_ObjIsAnd(pObj) && pObj->nRefs ) - Vec_PtrPush( vOrder, pObj ); - return vOrder; -} - -//////////////////////////////////////////////////////////////////////// -/// 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 c14428da..00000000 --- a/src/map/if/module.make +++ /dev/null @@ -1,8 +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/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 index b18b68c0..e59fa4a3 100644 --- a/src/map/mapper/mapper.c +++ b/src/map/mapper/mapper.c @@ -28,7 +28,7 @@ static int Map_CommandReadLibrary ( Abc_Frame_t * pAbc, int argc, char **argv ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -61,7 +61,7 @@ void Map_Init( Abc_Frame_t * pAbc ) void Map_End() { // Map_SuperLibFree( s_pSuperLib ); - Map_SuperLibFree( Abc_FrameReadLibSuper() ); + Map_SuperLibFree( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) ); } @@ -87,7 +87,7 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) int fAlgorithm; int c; - pNet = Abc_FrameReadNtk(pAbc); + pNet = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); @@ -95,16 +95,16 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) fVerbose = 1; fAlgorithm = 1; ExcludeFile = 0; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "eovh")) != EOF ) + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "eovh")) != EOF ) { switch (c) { case 'e': - ExcludeFile = argv[globalUtilOptind]; + ExcludeFile = argv[util_optind]; if ( ExcludeFile == 0 ) goto usage; - globalUtilOptind++; + util_optind++; break; case 'o': fAlgorithm ^= 1; @@ -121,15 +121,15 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != globalUtilOptind + 1 ) + if ( argc != util_optind + 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 ) + FileName = argv[util_optind]; +// if ( (pFile = Io_FileOpen( FileName, "open_path", "r" )) == 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 ) ) diff --git a/src/map/mapper/mapper.h b/src/map/mapper/mapper.h index 8eade761..c3f1ce81 100644 --- a/src/map/mapper/mapper.h +++ b/src/map/mapper/mapper.h @@ -19,10 +19,6 @@ #ifndef __MAPPER_H__ #define __MAPPER_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -60,16 +56,16 @@ struct Map_TimeStruct_t_ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// -#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))) +#define Map_IsComplement(p) (((int)((long) (p) & 01))) +#define Map_Regular(p) ((Map_Node_t *)((unsigned)(p) & ~01)) +#define Map_Not(p) ((Map_Node_t *)((long)(p) ^ 01)) +#define Map_NotCond(p,c) ((Map_Node_t *)((long)(p) ^ (c))) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mapperCreate.c =============================================================*/ @@ -184,12 +180,7 @@ 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 /// //////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/map/mapper/mapperCanon.c b/src/map/mapper/mapperCanon.c index 203c9142..2b0f261f 100644 --- a/src/map/mapper/mapperCanon.c +++ b/src/map/mapper/mapperCanon.c @@ -26,7 +26,7 @@ static unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigne static void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -218,7 +218,7 @@ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned u if ( uCanon0 >= uCanon1 ) // using nCanon1 as the main one { assert( p->pCounters[uTruth1] > 0 ); - uCanonBest = 0xFFFFFFFF; + uCanonBest = 0xFFFF; for ( i = 0; i < p->pCounters[uTruth1]; i++ ) { uCanon0 = Extra_TruthPolarize( uTruth0, p->uPhases[uTruth1][i], 4 ); @@ -226,7 +226,6 @@ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned u { uCanonBest = uCanon0; uPhaseBest = p->uPhases[uTruth1][i]; - assert( uPhaseBest < 16 ); } } uTruthRes[0] = (uCanon1 << 16) | uCanonBest; @@ -237,7 +236,7 @@ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned u else if ( uCanon0 < uCanon1 ) { assert( p->pCounters[uTruth0] > 0 ); - uCanonBest = 0xFFFFFFFF; + uCanonBest = 0xFFFF; for ( i = 0; i < p->pCounters[uTruth0]; i++ ) { uCanon1 = Extra_TruthPolarize( uTruth1, p->uPhases[uTruth0][i], 4 ); @@ -245,7 +244,6 @@ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned u { uCanonBest = uCanon1; uPhaseBest = p->uPhases[uTruth0][i]; - assert( uPhaseBest < 16 ); } } uTruthRes[0] = (uCanon0 << 16) | uCanonBest; diff --git a/src/map/mapper/mapperCore.c b/src/map/mapper/mapperCore.c index 5d4854e6..629ba59d 100644 --- a/src/map/mapper/mapperCore.c +++ b/src/map/mapper/mapperCore.c @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -46,7 +46,7 @@ ***********************************************************************/ int Map_Mapping( Map_Man_t * p ) { - int fShowSwitching = 1; + int fShowSwitching = 0; int fUseAreaFlow = 1; int fUseExactArea = !p->fSwitching; int fUseExactAreaWithPhase = !p->fSwitching; @@ -93,11 +93,7 @@ PRT( "Time", p->timeMatch ); ////////////////////////////////////////////////////////////////////// if ( !p->fAreaRecovery ) - { - if ( p->fVerbose ) - Map_MappingPrintOutputArrivals( p ); return 1; - } ////////////////////////////////////////////////////////////////////// // perform area recovery using area flow diff --git a/src/map/mapper/mapperCreate.c b/src/map/mapper/mapperCreate.c index 157d467b..31fbf0ea 100644 --- a/src/map/mapper/mapperCreate.c +++ b/src/map/mapper/mapperCreate.c @@ -30,7 +30,7 @@ static Map_Node_t * Map_TableLookup( Map_Man_t * p, Map_Node_t * p1, Map_Node 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -183,7 +183,7 @@ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ) int i; // derive the supergate library - if ( Abc_FrameReadLibSuper() == NULL ) + if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL ) { printf( "The supergate library is not specified. Use \"read_library\" or \"read_super\".\n" ); return NULL; @@ -192,7 +192,7 @@ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ) // start the manager p = ALLOC( Map_Man_t, 1 ); memset( p, 0, sizeof(Map_Man_t) ); - p->pSuperLib = Abc_FrameReadLibSuper(); + p->pSuperLib = Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()); p->nVarsMax = p->pSuperLib->nVarsMax; p->fVerbose = fVerbose; p->fEpsilon = (float)0.001; @@ -261,8 +261,8 @@ void Map_ManFree( Map_Man_t * p ) 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 ); + Extra_MmFixedStop( p->mmNodes, 0 ); + Extra_MmFixedStop( p->mmCuts, 0 ); FREE( p->pInputArrivals ); FREE( p->pInputs ); FREE( p->pOutputs ); @@ -314,7 +314,7 @@ void Map_ManPrintTimeStats( Map_Man_t * p ) void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, int Time ) { FILE * pTable; - pTable = fopen( "map_stats.txt", "a+" ); + pTable = fopen( "stats.txt", "a+" ); fprintf( pTable, "%s ", pName ); fprintf( pTable, "%4.2f ", Area ); fprintf( pTable, "%4.2f ", Delay ); diff --git a/src/map/mapper/mapperCut.c b/src/map/mapper/mapperCut.c index b05e9d0c..b5ce4018 100644 --- a/src/map/mapper/mapperCut.c +++ b/src/map/mapper/mapperCut.c @@ -80,7 +80,7 @@ static unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Ma pCut2 = pCut? pCut->pNext: NULL ) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -149,7 +149,7 @@ void Map_MappingCuts( Map_Man_t * p ) if ( p->fVerbose ) { nCuts = Map_MappingCountAllCuts(p); - printf( "Nodes = %6d. Total %d-feasible cuts = %10d. Per node = %.1f. ", + printf( "Nodes = %6d. Total %d-feasible cuts = %d. Per node = %.1f. ", p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); PRT( "Time", clock() - clk ); } @@ -208,7 +208,7 @@ Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * // set at the node pNode->pCuts = pCut; // remove the dominated cuts - Map_CutFilter( p, pNode ); +// Map_CutFilter( p, pNode ); // set the phase correctly if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) ) { @@ -612,8 +612,7 @@ int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[ { 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 ) + if ( ppNodes[k] < ppNodes[min] ) min = k; pNodeTemp = ppNodes[i]; ppNodes[i] = ppNodes[min]; diff --git a/src/map/mapper/mapperCutUtils.c b/src/map/mapper/mapperCutUtils.c index 4450cb04..9f572e75 100644 --- a/src/map/mapper/mapperCutUtils.c +++ b/src/map/mapper/mapperCutUtils.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/mapper/mapperFanout.c b/src/map/mapper/mapperFanout.c index 63cdbd2a..aca29918 100644 --- a/src/map/mapper/mapperFanout.c +++ b/src/map/mapper/mapperFanout.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/mapper/mapperGENERIC.c b/src/map/mapper/mapperGENERIC.c index 823eb4f2..4df5ee51 100644 --- a/src/map/mapper/mapperGENERIC.c +++ b/src/map/mapper/mapperGENERIC.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/mapper/mapperInt.h b/src/map/mapper/mapperInt.h index 37cca3d3..0acca56c 100644 --- a/src/map/mapper/mapperInt.h +++ b/src/map/mapper/mapperInt.h @@ -41,7 +41,7 @@ //#define MAP_ALLOCATE_FANOUT 1 //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // the bit masks @@ -61,10 +61,10 @@ #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))) +#define Map_CutIsComplement(p) (((int)((long) (p) & 01))) +#define Map_CutRegular(p) ((Map_Cut_t *)((unsigned)(p) & ~01)) +#define Map_CutNot(p) ((Map_Cut_t *)((long)(p) ^ 01)) +#define Map_CutNotCond(p,c) ((Map_Cut_t *)((long)(p) ^ (c))) // internal macros for referencing of nodes #define Map_NodeReadRef(p) ((Map_Regular(p))->nRefs) @@ -347,7 +347,7 @@ struct Map_HashEntryStruct_t_ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mapperCanon.c =============================================================*/ @@ -470,8 +470,8 @@ extern void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_No extern Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i ); extern void Map_NodeVecSortByLevel( Map_NodeVec_t * p ); -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/map/mapper/mapperLib.c b/src/map/mapper/mapperLib.c index d916487e..a9e9e29b 100644 --- a/src/map/mapper/mapperLib.c +++ b/src/map/mapper/mapperLib.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -147,9 +147,9 @@ void Map_SuperLibFree( Map_SuperLib_t * p ) Map_SuperTableFree( p->tTableC ); if ( p->tTable ) Map_SuperTableFree( p->tTable ); - Extra_MmFixedStop( p->mmSupers ); - Extra_MmFixedStop( p->mmEntries ); - Extra_MmFlexStop( p->mmForms ); + Extra_MmFixedStop( p->mmSupers, 0 ); + Extra_MmFixedStop( p->mmEntries, 0 ); + Extra_MmFlexStop( p->mmForms, 0 ); FREE( p->ppSupers ); FREE( p ); } @@ -179,7 +179,7 @@ int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib ) return 0; // write the current library into the file - sprintf( FileNameGenlib, "%s_temp", Mio_LibraryReadName(pLib) ); + strcpy( FileNameGenlib, Mio_LibraryReadName(pLib) ); pFile = fopen( FileNameGenlib, "w" ); Mio_WriteLibrary( pFile, pLib, 0 ); fclose( pFile ); diff --git a/src/map/mapper/mapperMatch.c b/src/map/mapper/mapperMatch.c index bfa72601..ddb9ebb7 100644 --- a/src/map/mapper/mapperMatch.c +++ b/src/map/mapper/mapperMatch.c @@ -41,7 +41,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/mapper/mapperRefs.c b/src/map/mapper/mapperRefs.c index a50b134a..baaebfa1 100644 --- a/src/map/mapper/mapperRefs.c +++ b/src/map/mapper/mapperRefs.c @@ -28,7 +28,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -237,7 +237,7 @@ 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 ); + assert( aResult == aResult2 ); return aResult; } @@ -257,7 +257,7 @@ 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 ); + assert( aResult == aResult2 ); return aResult; } diff --git a/src/map/mapper/mapperSuper.c b/src/map/mapper/mapperSuper.c index ce6a780f..34b1d8e6 100644 --- a/src/map/mapper/mapperSuper.c +++ b/src/map/mapper/mapperSuper.c @@ -30,7 +30,7 @@ static void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * static void Map_LibraryPrintClasses( Map_SuperLib_t * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/mapper/mapperSwitch.c b/src/map/mapper/mapperSwitch.c index 9dd6e42b..13168b47 100644 --- a/src/map/mapper/mapperSwitch.c +++ b/src/map/mapper/mapperSwitch.c @@ -25,7 +25,7 @@ static float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**function************************************************************* diff --git a/src/map/mapper/mapperTable.c b/src/map/mapper/mapperTable.c index d0cb7a01..747fe1c8 100644 --- a/src/map/mapper/mapperTable.c +++ b/src/map/mapper/mapperTable.c @@ -28,7 +28,7 @@ static void Map_SuperTableResize( Map_HashTable_t * pLib ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -325,7 +325,7 @@ void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax ) ppSupers[nSupers++] = pSuper; // sort by usage - qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), + qsort( (void *)ppSupers, nSupers, sizeof(int), (int (*)(const void *, const void *)) Map_SuperTableCompareSupergates ); assert( Map_SuperTableCompareSupergates( ppSupers, ppSupers + nSupers - 1 ) <= 0 ); @@ -380,7 +380,7 @@ void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax ) if ( nSupers == 0 ) continue; // sort the gates by delay - qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), + qsort( (void *)ppSupers, nSupers, sizeof(int), (int (*)(const void *, const void *)) Map_SuperTableCompareGatesInList ); assert( Map_SuperTableCompareGatesInList( ppSupers, ppSupers + nSupers - 1 ) <= 0 ); // link them in the reverse order diff --git a/src/map/mapper/mapperTime.c b/src/map/mapper/mapperTime.c index cc4173cf..f1cafae7 100644 --- a/src/map/mapper/mapperTime.c +++ b/src/map/mapper/mapperTime.c @@ -27,7 +27,7 @@ static void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, static float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**function************************************************************* diff --git a/src/map/mapper/mapperTree.c b/src/map/mapper/mapperTree.c index ef66082d..04576045 100644 --- a/src/map/mapper/mapperTree.c +++ b/src/map/mapper/mapperTree.c @@ -37,7 +37,7 @@ static unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ); extern const int s_MapFanoutLimits[10] = { 1/*0*/, 10/*1*/, 5/*2*/, 2/*3*/, 1/*4*/, 1/*5*/, 1/*6*/ }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -60,8 +60,8 @@ int Map_LibraryReadTree( Map_SuperLib_t * pLib, char * pFileName, char * pExclud // read the beginning of the file assert( pLib->pGenlib == NULL ); - pFile = Io_FileOpen( pFileName, "open_path", "r", 1 ); -// pFile = fopen( pFileName, "r" ); +// pFile = Io_FileOpen( pFileName, "open_path", "r" ); + pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); @@ -149,8 +149,8 @@ int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileNam } #endif - pFileGen = Io_FileOpen( pLibFile, "open_path", "r", 1 ); -// pFileGen = fopen( pLibFile, "r" ); +// pFileGen = Io_FileOpen( pLibFile, "open_path", "r" ); + pFileGen = fopen( pLibFile, "r" ); if ( pFileGen == NULL ) { printf( "Cannot open the GENLIB file \"%s\".\n", pLibFile ); @@ -439,9 +439,6 @@ int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate ) 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 diff --git a/src/map/mapper/mapperTruth.c b/src/map/mapper/mapperTruth.c index 388b6dd3..7eabf4df 100644 --- a/src/map/mapper/mapperTruth.c +++ b/src/map/mapper/mapperTruth.c @@ -27,7 +27,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -89,15 +89,14 @@ void Map_MappingTruths( Map_Man_t * pMan ) ***********************************************************************/ 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 + int fUseFast = 0; + int fUseRec = 1; extern int Map_CanonCompute( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ); @@ -118,8 +117,6 @@ void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut ) // 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 ); @@ -148,8 +145,6 @@ void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut ) 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 ); diff --git a/src/map/mapper/mapperUtils.c b/src/map/mapper/mapperUtils.c index 11a3a683..00f1b85b 100644 --- a/src/map/mapper/mapperUtils.c +++ b/src/map/mapper/mapperUtils.c @@ -40,7 +40,7 @@ static int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices ); static Map_Man_t * s_pMan = NULL; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// diff --git a/src/map/mapper/mapperVec.c b/src/map/mapper/mapperVec.c index f75138fb..e3ab4b7f 100644 --- a/src/map/mapper/mapperVec.c +++ b/src/map/mapper/mapperVec.c @@ -25,7 +25,7 @@ static int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index 10a5af9d..bb6dbba1 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -55,7 +55,7 @@ static char * pMcncGenlib[25] = { }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -108,7 +108,7 @@ void Mio_Init( Abc_Frame_t * pAbc ) void Mio_End() { // Mio_LibraryDelete( s_pLib ); - Mio_LibraryDelete( Abc_FrameReadLibGen() ); + Mio_LibraryDelete( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) ); } @@ -133,14 +133,14 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) int fVerbose; int c; - pNet = Abc_FrameReadNtk(pAbc); + pNet = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "vh")) != EOF ) { switch (c) { @@ -156,14 +156,14 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != globalUtilOptind + 1 ) + if ( argc != util_optind + 1 ) { goto usage; } // get the input file name - FileName = argv[globalUtilOptind]; - if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) + FileName = argv[util_optind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) ) @@ -181,7 +181,7 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } // free the current superlib because it depends on the old Mio library - if ( Abc_FrameReadLibSuper() ) + if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) ) { extern void Map_SuperLibFree( Map_SuperLib_t * p ); // Map_SuperLibFree( s_pSuperLib ); @@ -223,14 +223,14 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) int fVerbose; int c; - pNet = Abc_FrameReadNtk(pAbc); + pNet = Abc_FrameReadNet(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "vh")) != EOF ) { switch (c) { @@ -246,13 +246,13 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != globalUtilOptind ) + if ( argc != util_optind ) { goto usage; } // set the new network - Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(), 0 ); + Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()), 0 ); return 0; usage: diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h index dbe2420b..f9f4973d 100644 --- a/src/map/mio/mio.h +++ b/src/map/mio/mio.h @@ -19,10 +19,6 @@ #ifndef __MIO_H__ #define __MIO_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -46,7 +42,7 @@ typedef struct Mio_PinStruct_t_ Mio_Pin_t; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// #define Mio_LibraryForEachGate( Lib, Gate ) \ @@ -72,7 +68,7 @@ typedef struct Mio_PinStruct_t_ Mio_Pin_t; Pin2 = (Pin? Mio_PinReadNext(Pin): NULL) ) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mioApi.c =============================================================*/ @@ -85,7 +81,6 @@ extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char 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 ); @@ -94,11 +89,9 @@ 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 ); @@ -121,8 +114,8 @@ 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 ); +extern Mio_Library_t * Mio_LibraryRead( Abc_Frame_t * pAbc, char * FileName, char * ExcludeFile, int fVerbose ); +extern int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * tExcludeGate ); /*=== mioFunc.c =============================================================*/ extern int Mio_LibraryParseFormulas( Mio_Library_t * pLib ); /*=== mioUtils.c =============================================================*/ @@ -138,13 +131,7 @@ extern void Mio_DeriveGateDelays( Mio_Gate_t * pGate, float * ptDelaysRes, float * ptPinDelayMax ); extern Mio_Gate_t * Mio_GateCreatePseudo( int nInputs ); -#ifdef __cplusplus -} -#endif - -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// - +#endif diff --git a/src/map/mio/mioApi.c b/src/map/mio/mioApi.c index 73473f8b..a39c6288 100644 --- a/src/map/mio/mioApi.c +++ b/src/map/mio/mioApi.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -43,45 +43,19 @@ Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { retur 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_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.] diff --git a/src/map/mio/mioFunc.c b/src/map/mio/mioFunc.c index 21a078f9..24b2fecb 100644 --- a/src/map/mio/mioFunc.c +++ b/src/map/mio/mioFunc.c @@ -35,7 +35,7 @@ static int Mio_GateParseFormula( Mio_Gate_t * pGate ); static int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -213,7 +213,7 @@ int Mio_GateParseFormula( Mio_Gate_t * pGate ) 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 ); + pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, pGate->pLib->vCube, -1 ); return 0; } @@ -253,7 +253,7 @@ int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ) break; if ( i == nPins ) { // cannot find this name; save it - pPinNames[nPins++] = Extra_UtilStrsav(pTemp); + pPinNames[nPins++] = util_strsav(pTemp); } // get the next name pTemp = strtok( NULL, " " ); diff --git a/src/map/mio/mioGENERIC.c b/src/map/mio/mioGENERIC.c index 972c4ffc..6a40bc52 100644 --- a/src/map/mio/mioGENERIC.c +++ b/src/map/mio/mioGENERIC.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/mio/mioInt.h b/src/map/mio/mioInt.h index 3f90b625..105e3d8d 100644 --- a/src/map/mio/mioInt.h +++ b/src/map/mio/mioInt.h @@ -60,7 +60,6 @@ struct Mio_LibraryStruct_t_ 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 @@ -107,19 +106,19 @@ struct Mio_PinStruct_t_ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mio.c =============================================================*/ /*=== mioRead.c =============================================================*/ /*=== mioUtils.c =============================================================*/ -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c index 13c2cdcd..f2778ca4 100644 --- a/src/map/mio/mioRead.c +++ b/src/map/mio/mioRead.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// static Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ); @@ -49,7 +49,7 @@ extern int isspace( int c ); // to silence the warning in VS SeeAlso [] ***********************************************************************/ -Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose ) +Mio_Library_t * Mio_LibraryRead( Abc_Frame_t * pAbc, char * FileName, char * ExcludeFile, int fVerbose ) { Mio_Library_t * pLib; int num; @@ -99,7 +99,7 @@ Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fE // allocate the genlib structure pLib = ALLOC( Mio_Library_t, 1 ); memset( pLib, 0, sizeof(Mio_Library_t) ); - pLib->pName = Extra_UtilStrsav( FileName ); + pLib->pName = util_strsav( FileName ); pLib->tName2Gate = st_init_table(strcmp, st_strhash); pLib->pMmFlex = Extra_MmFlexStart(); pLib->vCube = Vec_StrAlloc( 100 ); @@ -114,8 +114,8 @@ Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fE int nFileSize; // open the BLIF file for binary reading - pFile = Io_FileOpen( FileName, "open_path", "rb", 1 ); -// pFile = fopen( FileName, "rb" ); +// pFile = Io_FileOpen( FileName, "open_path", "rb" ); + pFile = fopen( FileName, "rb" ); // if we got this far, file should be okay otherwise would // have been detected by caller assert ( pFile != NULL ); @@ -251,7 +251,7 @@ Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat ) // read the name pToken = strtok( NULL, " \t\r\n" ); - pGate->pName = Extra_UtilStrsav( pToken ); + pGate->pName = util_strsav( pToken ); // read the area pToken = strtok( NULL, " \t\r\n" ); @@ -265,7 +265,7 @@ Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat ) // then rest of the expression pToken = strtok( NULL, ";" ); - pGate->pForm = Extra_UtilStrsav( pToken ); + pGate->pForm = util_strsav( pToken ); // read the pin info // start the linked list of pins @@ -319,7 +319,7 @@ Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat ) // read the name pToken = strtok( NULL, " \t\r\n" ); - pPin->pName = Extra_UtilStrsav( pToken ); + pPin->pName = util_strsav( pToken ); // read the pin phase pToken = strtok( NULL, " \t\r\n" ); @@ -418,14 +418,12 @@ char *chomp( char *s ) void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; - DdNode * bFuncBuf, * bFuncInv, * bFuncNand2, * bFuncAnd2; + DdNode * bFuncBuf, * bFuncInv, * bFuncNand2; 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 ) { @@ -437,8 +435,7 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ) 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 ) { @@ -451,28 +448,20 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ) 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 ) + if ( pLib->pGateNand2 == NULL ) { - printf( "Warnings: GENLIB library reader cannot detect the AND2 or NAND2 gate.\n" ); + printf( "Warnings: GENLIB library reader cannot detect the 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************************************************************* @@ -486,7 +475,7 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ) SeeAlso [] ***********************************************************************/ -int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate ) +int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * tExcludeGate ) { int nDel = 0; FILE *pEx; @@ -507,7 +496,7 @@ int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExclude while (1 == fscanf( pEx, "%127s", buffer )) { //printf ("Read: '%s'\n", buffer ); - st_insert( tExcludeGate, Extra_UtilStrsav( buffer ), (char *)0 ); + st_insert( tExcludeGate, util_strsav( buffer ), (char *)0 ); nDel++; } diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c index bd3d01f7..15f32890 100644 --- a/src/map/mio/mioUtils.c +++ b/src/map/mio/mioUtils.c @@ -28,7 +28,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -53,7 +53,7 @@ void Mio_LibraryDelete( Mio_Library_t * pLib ) FREE( pLib->pName ); Mio_LibraryForEachGateSafe( pLib, pGate, pGate2 ) Mio_GateDelete( pGate ); - Extra_MmFlexStop( pLib->pMmFlex ); + Extra_MmFlexStop( pLib->pMmFlex, 0 ); Vec_StrFree( pLib->vCube ); if ( pLib->tName2Gate ) st_free_table( pLib->tName2Gate ); @@ -120,7 +120,7 @@ Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ) pPinNew = ALLOC( Mio_Pin_t, 1 ); *pPinNew = *pPin; - pPinNew->pName = (pPinNew->pName ? Extra_UtilStrsav(pPinNew->pName) : NULL); + pPinNew->pName = (pPinNew->pName ? util_strsav(pPinNew->pName) : NULL); pPinNew->pNext = NULL; return pPinNew; @@ -165,9 +165,9 @@ 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, "%12s ", pGate->pName ); fprintf( pFile, "%10.2f ", pGate->dArea ); - fprintf( pFile, "%s=%s;\n", pGate->pOutName, pGate->pForm ); + fprintf( pFile, "O=%s;\n", pGate->pForm ); // print the pins if ( fPrintSops ) fprintf( pFile, "%s", pGate->pSop? pGate->pSop : "unspecified\n" ); 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/ply/module.make b/src/map/ply/module.make deleted file mode 100644 index e69de29b..00000000 diff --git a/src/map/super/super.c b/src/map/super/super.c index 97420c5c..ffb432d5 100644 --- a/src/map/super/super.c +++ b/src/map/super/super.c @@ -28,7 +28,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -90,20 +90,20 @@ int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv ) nVarsMax = 4; nLevels = 3; fVerbose = 0; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "ilvh")) != EOF ) + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "ilvh")) != EOF ) { switch (c) { case 'i': - nVarsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; + nVarsMax = atoi(argv[util_optind]); + util_optind++; if ( nVarsMax < 0 ) goto usage; break; case 'l': - nLevels = atoi(argv[globalUtilOptind]); - globalUtilOptind++; + nLevels = atoi(argv[util_optind]); + util_optind++; if ( nLevels < 0 ) goto usage; break; @@ -172,44 +172,44 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) fWriteOldFormat = 0; ExcludeFile = 0; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "eiltdasovh")) != EOF ) + util_getopt_reset(); + while ( (c = util_getopt(argc, argv, "eiltdasovh")) != EOF ) { switch (c) { case 'e': - ExcludeFile = argv[globalUtilOptind]; + ExcludeFile = argv[util_optind]; if ( ExcludeFile == 0 ) goto usage; - globalUtilOptind++; + util_optind++; break; case 'i': - nVarsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; + nVarsMax = atoi(argv[util_optind]); + util_optind++; if ( nVarsMax < 0 ) goto usage; break; case 'l': - nLevels = atoi(argv[globalUtilOptind]); - globalUtilOptind++; + nLevels = atoi(argv[util_optind]); + util_optind++; if ( nLevels < 0 ) goto usage; break; case 't': - TimeLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; + TimeLimit = atoi(argv[util_optind]); + util_optind++; if ( TimeLimit < 0 ) goto usage; break; case 'd': - DelayLimit = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; + DelayLimit = (float)atof(argv[util_optind]); + util_optind++; if ( DelayLimit <= 0.0 ) goto usage; break; case 'a': - AreaLimit = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; + AreaLimit = (float)atof(argv[util_optind]); + util_optind++; if ( AreaLimit <= 0.0 ) goto usage; break; @@ -231,7 +231,7 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != globalUtilOptind + 1 ) + if ( argc != util_optind + 1 ) { fprintf( pErr, "The GENLIB library file should be given on the command line.\n" ); goto usage; @@ -244,9 +244,9 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) } // get the input file name - FileName = argv[globalUtilOptind]; - if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) -// if ( (pFile = fopen( FileName, "r" )) == NULL ) + FileName = argv[util_optind]; +// if ( (pFile = Io_FileOpen( FileName, "open_path", "r" )) == 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 ) )) diff --git a/src/map/super/super.h b/src/map/super/super.h index a7169924..ce2b7433 100644 --- a/src/map/super/super.h +++ b/src/map/super/super.h @@ -19,10 +19,6 @@ #ifndef __SUPER_H__ #define __SUPER_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -40,21 +36,16 @@ extern "C" { //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== superCore.c =============================================================*/ - -#ifdef __cplusplus -} -#endif - -#endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/map/super/superAnd.c b/src/map/super/superAnd.c index 52473fba..e90fc76d 100644 --- a/src/map/super/superAnd.c +++ b/src/map/super/superAnd.c @@ -61,10 +61,10 @@ struct Super2_GateStruct_t_ // 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))) +#define Super2_IsComplement(p) (((int)((long) (p) & 01))) +#define Super2_Regular(p) ((Super2_Gate_t *)((unsigned)(p) & ~01)) +#define Super2_Not(p) ((Super2_Gate_t *)((long)(p) ^ 01)) +#define Super2_NotCond(p,c) ((Super2_Gate_t *)((long)(p) ^ (c))) // iterating through the gates in the library #define Super2_LibForEachGate( Lib, Gate ) \ @@ -93,7 +93,7 @@ static int Super2_LibWriteCompare( char * pStr1, char * pStr2 ); static int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -183,7 +183,7 @@ Super2_Man_t * Super2_ManStart() ***********************************************************************/ void Super2_ManStop( Super2_Man_t * pMan ) { - Extra_MmFixedStop( pMan->pMem ); + Extra_MmFixedStop( pMan->pMem, 0 ); stmm_free_table( pMan->tTable ); free( pMan ); } diff --git a/src/map/super/superGENERIC.c b/src/map/super/superGENERIC.c index 1f2b7651..4c7b67ca 100644 --- a/src/map/super/superGENERIC.c +++ b/src/map/super/superGENERIC.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/map/super/superGate.c b/src/map/super/superGate.c index 91a1e513..d0cd0ad7 100644 --- a/src/map/super/superGate.c +++ b/src/map/super/superGate.c @@ -120,7 +120,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -886,7 +886,7 @@ Super_Man_t * Super_ManStart() ***********************************************************************/ void Super_ManStop( Super_Man_t * pMan ) { - Extra_MmFixedStop( pMan->pMem ); + Extra_MmFixedStop( pMan->pMem, 0 ); if ( pMan->tTable ) stmm_free_table( pMan->tTable ); FREE( pMan->pGates ); free( pMan ); diff --git a/src/map/super/superInt.h b/src/map/super/superInt.h index ec6d0a38..686c8739 100644 --- a/src/map/super/superInt.h +++ b/src/map/super/superInt.h @@ -43,11 +43,11 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== superAnd.c =============================================================*/ @@ -55,8 +55,8 @@ 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 /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/map/super/superWrite.c b/src/map/super/superWrite.c index 395ef145..a0e85604 100644 --- a/src/map/super/superWrite.c +++ b/src/map/super/superWrite.c @@ -53,7 +53,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* 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 index 314257a2..f36b113f 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -29,10 +29,6 @@ #ifndef __EXTRA_H__ #define __EXTRA_H__ -#ifdef __cplusplus -extern "C" { -#endif - #ifdef _WIN32 #define inline __inline // compatible with MS VS 6.0 #endif @@ -41,15 +37,9 @@ extern "C" { /* 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 "util.h" #include "st.h" #include "cuddInt.h" @@ -73,15 +63,6 @@ extern "C" { /* 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 @@ -110,59 +91,13 @@ typedef unsigned long long uint64; #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 ========================================================*/ - +/*=== extraUtilBdd.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 ); @@ -181,21 +116,6 @@ extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n 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 =================================================================*/ @@ -248,46 +168,6 @@ extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNo 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; @@ -311,7 +191,7 @@ 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 int Extra_FileNameCheckExtension( char * FileName, char * Extension ); extern char * Extra_FileNameAppend( char * pBase, char * pSuffix ); extern char * Extra_FileNameGeneric( char * FileName ); extern int Extra_FileSize( char * pFileName ); @@ -320,9 +200,6 @@ 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 ); @@ -346,28 +223,26 @@ 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 void Extra_MmFixedStop( Extra_MmFixed_t * p, int fVerbose ); 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 void Extra_MmFlexStop( Extra_MmFlex_t * p, int fVerbose ); 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 void Extra_MmStepStop( Extra_MmStep_t * p, int fVerbose ); 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 */ +/* finds the smallest integer larger of equal than the logarithm. */ extern int Extra_Base2Log( unsigned Num ); extern int Extra_Base2LogDouble( double Num ); extern int Extra_Base10Log( unsigned Num ); @@ -377,8 +252,6 @@ 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 */ @@ -399,14 +272,11 @@ extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhas 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 ); @@ -424,203 +294,31 @@ 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; +{ if ( nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); } + +/*=== extraUtilIntVec.c ================================================================*/ + +typedef struct Extra_IntVec_t_ Extra_IntVec_t; +extern Extra_IntVec_t * Extra_IntVecAlloc( int nCap ); +extern Extra_IntVec_t * Extra_IntVecAllocArray( int * pArray, int nSize ); +extern Extra_IntVec_t * Extra_IntVecAllocArrayCopy( int * pArray, int nSize ); +extern Extra_IntVec_t * Extra_IntVecDup( Extra_IntVec_t * pVec ); +extern Extra_IntVec_t * Extra_IntVecDupArray( Extra_IntVec_t * pVec ); +extern void Extra_IntVecFree( Extra_IntVec_t * p ); +extern void Extra_IntVecFill( Extra_IntVec_t * p, int nSize, int Entry ); +extern int * Extra_IntVecReleaseArray( Extra_IntVec_t * p ); +extern int * Extra_IntVecReadArray( Extra_IntVec_t * p ); +extern int Extra_IntVecReadSize( Extra_IntVec_t * p ); +extern int Extra_IntVecReadEntry( Extra_IntVec_t * p, int i ); +extern int Extra_IntVecReadEntryLast( Extra_IntVec_t * p ); +extern void Extra_IntVecWriteEntry( Extra_IntVec_t * p, int i, int Entry ); +extern void Extra_IntVecGrow( Extra_IntVec_t * p, int nCapMin ); +extern void Extra_IntVecShrink( Extra_IntVec_t * p, int nSizeNew ); +extern void Extra_IntVecClear( Extra_IntVec_t * p ); +extern void Extra_IntVecPush( Extra_IntVec_t * p, int Entry ); +extern int Extra_IntVecPop( Extra_IntVec_t * p ); +extern void Extra_IntVecSort( Extra_IntVec_t * p ); /**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 index a3320ad3..373ce5c5 100644 --- a/src/misc/extra/extraBddMisc.c +++ b/src/misc/extra/extraBddMisc.c @@ -14,7 +14,7 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $] + Revision [$Id: extraBddMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ @@ -50,13 +50,10 @@ // 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 ); +static void ddSupportStep ARGS((DdNode *f, int *support)); +static void ddClearFlag ARGS((DdNode *f)); /**AutomaticEnd***************************************************************/ @@ -687,280 +684,6 @@ DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) 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 */ /*---------------------------------------------------------------------------*/ @@ -1316,297 +1039,6 @@ ddClearFlag( } /* 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 index 358402b0..474f663f 100644 --- a/src/misc/extra/extraBddSymm.c +++ b/src/misc/extra/extraBddSymm.c @@ -223,7 +223,7 @@ Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ) /**Function******************************************************************** - Synopsis [Deallocates symmetry information structure.] + Synopsis [Delocates symmetry information structure.] Description [] 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 index b860a538..93cbbeac 100644 --- a/src/misc/extra/extraUtilBitMatrix.c +++ b/src/misc/extra/extraUtilBitMatrix.c @@ -348,7 +348,7 @@ 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 ); + nTotal += ( (p->ppData[i][k/32] & (1 << (k%32))) > 0 ); return nTotal; } diff --git a/src/misc/extra/extraUtilCanon.c b/src/misc/extra/extraUtilCanon.c index fcc7d84d..9d4e5b5d 100644 --- a/src/misc/extra/extraUtilCanon.c +++ b/src/misc/extra/extraUtilCanon.c @@ -99,8 +99,7 @@ int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned Description [] - SideEffects [This procedure has a bug, which shows on Solaris. - Most likely has something to do with the casts, i.g *((unsigned *)pt0)] + SideEffects [] SeeAlso [] @@ -130,22 +129,21 @@ int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, ch pt0 = pt; pt1 = pt + (1 << nVarsN) / 8; // 5-var truth tables for this call -// uInit0 = *((unsigned *)pt0); -// uInit1 = *((unsigned *)pt1); + 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]; + uInit0 &= 0xFF; + uInit1 &= 0xFF; + uInit0 = (uInit0 << 24) | (uInit0 << 16) | (uInit0 << 8) | uInit0; + uInit1 = (uInit1 << 24) | (uInit1 << 16) | (uInit1 << 8) | uInit1; } 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]; + uInit0 &= 0xFFFF; + uInit1 &= 0xFFFF; + uInit0 = (uInit0 << 16) | uInit0; + uInit1 = (uInit1 << 16) | uInit1; } // storage for truth tables and phases diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c index 4c51b8b5..03b31fea 100644 --- a/src/misc/extra/extraUtilFile.c +++ b/src/misc/extra/extraUtilFile.c @@ -110,7 +110,7 @@ char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, /**Function************************************************************* - Synopsis [Returns the pointer to the file extension.] + Synopsis [] Description [] @@ -119,14 +119,21 @@ char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, SeeAlso [] ***********************************************************************/ -char * Extra_FileNameExtension( char * FileName ) +int Extra_FileNameCheckExtension( char * FileName, char * Extension ) { char * pDot; - // find the last "dot" in the file name, if it is present + // find "dot" if it is present in the file name +// pDot = strstr( FileName, "." ); for ( pDot = FileName + strlen(FileName)-1; pDot >= FileName; pDot-- ) if ( *pDot == '.' ) - return pDot + 1; - return NULL; + break; + if ( *pDot != '.' ) + return 0; + // check the extension + if ( pDot && strcmp( pDot+1, Extension ) == 0 ) + return 1; + else + return 0; } /**Function************************************************************* @@ -165,7 +172,7 @@ char * Extra_FileNameGeneric( char * FileName ) char * pRes; // find the generic name of the file - pRes = Extra_UtilStrsav( FileName ); + pRes = util_strsav( FileName ); // find the pointer to the "." symbol in the file name // pUnd = strstr( FileName, "_" ); pUnd = NULL; @@ -248,8 +255,8 @@ char * Extra_FileRead( FILE * pFile ) char * Extra_TimeStamp() { static char Buffer[100]; - char * TimeStamp; time_t ltime; + char * TimeStamp; // get the current time time( <ime ); TimeStamp = asctime( localtime( <ime ) ); @@ -311,97 +318,6 @@ void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ) // 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.] @@ -475,7 +391,7 @@ char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ) free( pStrGiven ); } else - pTemp = Extra_UtilStrsav( pStrAdd ); + pTemp = util_strsav( pStrAdd ); return pTemp; } diff --git a/src/misc/extra/extraUtilMemory.c b/src/misc/extra/extraUtilMemory.c index 6eccf015..af1128ac 100644 --- a/src/misc/extra/extraUtilMemory.c +++ b/src/misc/extra/extraUtilMemory.c @@ -73,9 +73,6 @@ struct Extra_MmStep_t_ 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 }; /*---------------------------------------------------------------------------*/ @@ -155,30 +152,18 @@ Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize ) 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 ) +void Extra_MmFixedStop( Extra_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 ); @@ -272,7 +257,7 @@ void Extra_MmFixedRestart( Extra_MmFixed_t * p ) int i; char * pTemp; - // deallocate all chunks except the first one + // delocate all chunks except the first one for ( i = 1; i < p->nChunks; i++ ) free( p->pChunks[i] ); p->nChunks = 1; @@ -310,21 +295,6 @@ 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************************************************************* @@ -341,7 +311,7 @@ int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p ) 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) ); @@ -349,7 +319,7 @@ Extra_MmFlex_t * Extra_MmFlexStart() p->pCurrent = NULL; p->pEnd = NULL; - p->nChunkSize = (1 << 10); + p->nChunkSize = (1 << 12); p->nChunksAlloc = 64; p->nChunks = 0; p->pChunks = ALLOC( char *, p->nChunksAlloc ); @@ -370,31 +340,18 @@ Extra_MmFlex_t * Extra_MmFlexStart() 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 ) +void Extra_MmFlexStop( Extra_MmFlex_t * p, int fVerbose ) { int i; if ( p == NULL ) return; -//printf( "deleting flex\n" ); + 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 ); @@ -491,7 +448,6 @@ 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 ); @@ -522,17 +478,11 @@ Extra_MmStep_t * Extra_MmStepStart( int nSteps ) SeeAlso [] ***********************************************************************/ -void Extra_MmStepStop( Extra_MmStep_t * p ) +void Extra_MmStepStop( Extra_MmStep_t * p, int fVerbose ) { 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 ); -// } + Extra_MmFixedStop( p->pMems[i], fVerbose ); free( p->pMems ); free( p->pMap ); free( p ); @@ -556,17 +506,6 @@ char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes ) 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] ); diff --git a/src/misc/extra/extraUtilMisc.c b/src/misc/extra/extraUtilMisc.c index dff774bc..6d771990 100644 --- a/src/misc/extra/extraUtilMisc.c +++ b/src/misc/extra/extraUtilMisc.c @@ -209,37 +209,6 @@ int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits ) return Code; } -/**Function************************************************************* - - Synopsis [Counts the number of ones in the bitstring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_CountOnes( unsigned char * pBytes, int nBytes ) -{ - 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 - }; - - int i, Counter; - Counter = 0; - for ( i = 0; i < nBytes; i++ ) - Counter += bit_count[ *(pBytes+i) ]; - return Counter; -} - /**Function******************************************************************** Synopsis [Computes the factorial.] @@ -1303,635 +1272,6 @@ void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes ) } } -/**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.] @@ -2039,84 +1379,6 @@ unsigned ** Extra_TruthPerm63() 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.] @@ -2153,6 +1415,7 @@ unsigned int Cudd_PrimeCopy( unsigned int p) } /* end of Cudd_Prime */ + /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ @@ -2162,72 +1425,6 @@ unsigned int Cudd_PrimeCopy( unsigned int p) /*---------------------------------------------------------------------------*/ -/**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 index 6b6d5132..7b0efb5c 100644 --- a/src/misc/extra/extraUtilProgress.c +++ b/src/misc/extra/extraUtilProgress.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include +#include "stdio.h" #include "extra.h" //////////////////////////////////////////////////////////////////////// @@ -38,7 +38,7 @@ static void Extra_ProgressBarShow( ProgressBar * p, char * pString ); static void Extra_ProgressBarClean( ProgressBar * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -58,17 +58,13 @@ static void Extra_ProgressBarClean( ProgressBar * p ); 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); + p->nItemsNext = (int)((float)p->nItemsTotal/p->posTotal)*(p->posCur+5)+2; Extra_ProgressBarShow( p, NULL ); return p; } @@ -86,19 +82,14 @@ ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ) ***********************************************************************/ 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); - } + if ( nItemsCur > p->nItemsTotal ) + nItemsCur = p->nItemsTotal; + p->posCur = (int)((float)nItemsCur * p->posTotal / p->nItemsTotal); + p->nItemsNext = (int)((float)p->nItemsTotal/p->posTotal)*(p->posCur+10)+1; + if ( p->posCur == 0 ) + p->posCur = 1; Extra_ProgressBarShow( p, pString ); } @@ -116,7 +107,6 @@ void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ***********************************************************************/ void Extra_ProgressBarStop( ProgressBar * p ) { - if ( p == NULL ) return; Extra_ProgressBarClean( p ); FREE( p ); } @@ -135,7 +125,6 @@ void Extra_ProgressBarStop( ProgressBar * p ) 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++ ) @@ -162,7 +151,6 @@ void Extra_ProgressBarShow( ProgressBar * p, char * pString ) 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" ); diff --git a/src/misc/extra/extraUtilReader.c b/src/misc/extra/extraUtilReader.c index c165b989..042dfaca 100644 --- a/src/misc/extra/extraUtilReader.c +++ b/src/misc/extra/extraUtilReader.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include +#include "stdio.h" #include "extra.h" #include "vec.h" @@ -26,7 +26,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -#define EXTRA_BUFFER_SIZE 4*1048576 // 1M - size of the data chunk stored in memory +#define EXTRA_BUFFER_SIZE 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)) @@ -67,7 +67,7 @@ static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ); static void Extra_FileReaderReload( Extra_FileReader_t * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -262,9 +262,6 @@ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ) // 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++ ) { @@ -273,10 +270,6 @@ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ) 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: @@ -333,14 +326,6 @@ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ) 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; } 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 c685f7bc..00000000 --- a/src/misc/extra/extraUtilUtil.c +++ /dev/null @@ -1,356 +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 [The code contributed by Niklas Sorensson.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_UtilTildeExpand( char *fname ) -{ - return Extra_UtilStrsav( fname ); -/* - int n_tildes = 0; - const char* home; - char* expanded; - int length; - int i, j, k; - - for (i = 0; i < (int)strlen(fname); i++) - if (fname[i] == '~') n_tildes++; - - home = getenv("HOME"); - length = n_tildes * strlen(home) + strlen(fname); - expanded = ALLOC(char, length + 1); - - j = 0; - for (i = 0; i < (int)strlen(fname); i++){ - if (fname[i] == '~'){ - for (k = 0; k < (int)strlen(home); k++) - expanded[j++] = home[k]; - }else - expanded[j++] = fname[i]; - } - - expanded[j] = '\0'; - return expanded; -*/ -} - -/**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 index ec8bca4d..6cbf5d2c 100644 --- a/src/misc/extra/module.make +++ b/src/misc/extra/module.make @@ -1,15 +1,9 @@ -SRC += src/misc/extra/extraBddAuto.c \ - src/misc/extra/extraBddCas.c \ - src/misc/extra/extraBddKmap.c \ - src/misc/extra/extraBddMisc.c \ +SRC += 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 + src/misc/extra/extraUtilReader.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/hop/hop.h b/src/misc/hop/hop.h new file mode 100644 index 00000000..37096473 --- /dev/null +++ b/src/misc/hop/hop.h @@ -0,0 +1,345 @@ +/**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 long Type : 3; // object type + unsigned long fPhase : 1; // value under 000...0 pattern + unsigned long fMarkA : 1; // multipurpose mask + unsigned long fMarkB : 1; // multipurpose mask + unsigned long 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 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 /// +//////////////////////////////////////////////////////////////////////// + +/*=== aigBalance.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 ); +/*=== aigCheck.c ========================================================*/ +extern int Hop_ManCheck( Hop_Man_t * p ); +/*=== aigDfs.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 ); +/*=== aigMan.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 ); +/*=== aigMem.c ==========================================================*/ +extern void Hop_ManStartMemory( Hop_Man_t * p ); +extern void Hop_ManStopMemory( Hop_Man_t * p ); +/*=== aigObj.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 ); +/*=== aigOper.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 ); +/*=== aigTable.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 ); +/*=== aigUtil.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/misc/hop/hopBalance.c b/src/misc/hop/hopBalance.c new file mode 100644 index 00000000..73c90685 --- /dev/null +++ b/src/misc/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/src/misc/hop/hopCheck.c b/src/misc/hop/hopCheck.c new file mode 100644 index 00000000..9120906f --- /dev/null +++ b/src/misc/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/src/misc/hop/hopDfs.c b/src/misc/hop/hopDfs.c new file mode 100644 index 00000000..49e5f221 --- /dev/null +++ b/src/misc/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/src/misc/hop/hopMan.c b/src/misc/hop/hopMan.c new file mode 100644 index 00000000..99f5d316 --- /dev/null +++ b/src/misc/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/src/misc/hop/hopMem.c b/src/misc/hop/hopMem.c new file mode 100644 index 00000000..0665470a --- /dev/null +++ b/src/misc/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/src/misc/hop/hopObj.c b/src/misc/hop/hopObj.c new file mode 100644 index 00000000..c8e70dd3 --- /dev/null +++ b/src/misc/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/src/misc/hop/hopOper.c b/src/misc/hop/hopOper.c new file mode 100644 index 00000000..a31ca0f2 --- /dev/null +++ b/src/misc/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/src/misc/hop/hopTable.c b/src/misc/hop/hopTable.c new file mode 100644 index 00000000..8e61ef36 --- /dev/null +++ b/src/misc/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 ^= (long)Hop_ObjFanin0(pObj) * 7937; + Key ^= (long)Hop_ObjFanin1(pObj) * 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/misc/hop/hopUtil.c b/src/misc/hop/hopUtil.c new file mode 100644 index 00000000..2fb595cd --- /dev/null +++ b/src/misc/hop/hopUtil.c @@ -0,0 +1,576 @@ +/**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 = Extra_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/misc/hop/hop_.c b/src/misc/hop/hop_.c new file mode 100644 index 00000000..468413fa --- /dev/null +++ b/src/misc/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/src/misc/hop/module.make b/src/misc/hop/module.make new file mode 100644 index 00000000..b06d91fd --- /dev/null +++ b/src/misc/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/src/misc/mvc/mvc.c b/src/misc/mvc/mvc.c index 001b1c63..9430276c 100644 --- a/src/misc/mvc/mvc.c +++ b/src/misc/mvc/mvc.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvc.h b/src/misc/mvc/mvc.h index 70834e0a..ee8c31be 100644 --- a/src/misc/mvc/mvc.h +++ b/src/misc/mvc/mvc.h @@ -24,8 +24,9 @@ //////////////////////////////////////////////////////////////////////// #include +#include "util.h" #include "extra.h" -#include "extra.h" +//#include "vm.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -49,7 +50,7 @@ //////////////////////////////////////////////////////////////////////// // cube/list/cover/data -typedef unsigned int Mvc_CubeWord_t; +typedef unsigned long Mvc_CubeWord_t; typedef struct MvcCubeStruct Mvc_Cube_t; typedef struct MvcListStruct Mvc_List_t; typedef struct MvcCoverStruct Mvc_Cover_t; @@ -111,7 +112,7 @@ struct MvcManagerStruct }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // reading data from the header of the cube @@ -565,7 +566,7 @@ struct MvcManagerStruct #define MEM_FREE( Manager, Type, Size, Pointer ) if ( Pointer ) { free(Pointer); Pointer = NULL; } //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mvcApi.c ====================================================*/ @@ -724,9 +725,9 @@ 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 /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/misc/mvc/mvcApi.c b/src/misc/mvc/mvcApi.c index eb942f93..1f51a235 100644 --- a/src/misc/mvc/mvcApi.c +++ b/src/misc/mvc/mvcApi.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcCompare.c b/src/misc/mvc/mvcCompare.c index 9cff99cd..c7999d40 100644 --- a/src/misc/mvc/mvcCompare.c +++ b/src/misc/mvc/mvcCompare.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcContain.c b/src/misc/mvc/mvcContain.c index a9eae06e..37b933b8 100644 --- a/src/misc/mvc/mvcContain.c +++ b/src/misc/mvc/mvcContain.c @@ -26,7 +26,7 @@ static void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover ); static void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/mvc/mvcCover.c b/src/misc/mvc/mvcCover.c index d8584446..bd9c4412 100644 --- a/src/misc/mvc/mvcCover.c +++ b/src/misc/mvc/mvcCover.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcCube.c b/src/misc/mvc/mvcCube.c index e157879f..d02fa270 100644 --- a/src/misc/mvc/mvcCube.c +++ b/src/misc/mvc/mvcCube.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcDivide.c b/src/misc/mvc/mvcDivide.c index 03643dcf..6aa3d58d 100644 --- a/src/misc/mvc/mvcDivide.c +++ b/src/misc/mvc/mvcDivide.c @@ -27,7 +27,7 @@ static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, M int s_fVerbose = 0; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcDivisor.c b/src/misc/mvc/mvcDivisor.c index ecdea75b..e92c3a65 100644 --- a/src/misc/mvc/mvcDivisor.c +++ b/src/misc/mvc/mvcDivisor.c @@ -25,7 +25,7 @@ static void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcList.c b/src/misc/mvc/mvcList.c index 8a82f911..678ae9fd 100644 --- a/src/misc/mvc/mvcList.c +++ b/src/misc/mvc/mvcList.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcLits.c b/src/misc/mvc/mvcLits.c index 910158e9..98211719 100644 --- a/src/misc/mvc/mvcLits.c +++ b/src/misc/mvc/mvcLits.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcMan.c b/src/misc/mvc/mvcMan.c index 7b4ef2af..f2943e0c 100644 --- a/src/misc/mvc/mvcMan.c +++ b/src/misc/mvc/mvcMan.c @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -63,10 +63,10 @@ Mvc_Manager_t * Mvc_ManagerStart() ***********************************************************************/ void Mvc_ManagerFree( Mvc_Manager_t * p ) { - Extra_MmFixedStop( p->pMan1 ); - Extra_MmFixedStop( p->pMan2 ); - Extra_MmFixedStop( p->pMan4 ); - Extra_MmFixedStop( p->pManC ); + Extra_MmFixedStop( p->pMan1, 0 ); + Extra_MmFixedStop( p->pMan2, 0 ); + Extra_MmFixedStop( p->pMan4, 0 ); + Extra_MmFixedStop( p->pManC, 0 ); free( p ); } diff --git a/src/misc/mvc/mvcOpAlg.c b/src/misc/mvc/mvcOpAlg.c index 65c02fa5..befccb70 100644 --- a/src/misc/mvc/mvcOpAlg.c +++ b/src/misc/mvc/mvcOpAlg.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcOpBool.c b/src/misc/mvc/mvcOpBool.c index 0b34f1de..57b1a968 100644 --- a/src/misc/mvc/mvcOpBool.c +++ b/src/misc/mvc/mvcOpBool.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcPrint.c b/src/misc/mvc/mvcPrint.c index 52ac76b3..3a31235b 100644 --- a/src/misc/mvc/mvcPrint.c +++ b/src/misc/mvc/mvcPrint.c @@ -27,7 +27,7 @@ static void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcSort.c b/src/misc/mvc/mvcSort.c index 3c975cb3..1126b22a 100644 --- a/src/misc/mvc/mvcSort.c +++ b/src/misc/mvc/mvcSort.c @@ -27,7 +27,7 @@ Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMa 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/misc/mvc/mvcUtils.c b/src/misc/mvc/mvcUtils.c index 4b13b23d..3fb57276 100644 --- a/src/misc/mvc/mvcUtils.c +++ b/src/misc/mvc/mvcUtils.c @@ -38,7 +38,7 @@ static void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNe //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* 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/st.c b/src/misc/st/st.c index 872fe51b..13e9bd6a 100644 --- a/src/misc/st/st.c +++ b/src/misc/st/st.c @@ -8,31 +8,12 @@ * */ #include -#include +#include "util.h" #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 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)) @@ -60,8 +41,8 @@ int reorder_flag; st_table *new; new = ALLOC(st_table, 1); - if (new == NULL) { - return NULL; + if (new == NIL(st_table)) { + return NIL(st_table); } new->compare = compare; new->hash = hash; @@ -74,9 +55,9 @@ int reorder_flag; } new->num_bins = size; new->bins = ALLOC(st_table_entry *, size); - if (new->bins == NULL) { + if (new->bins == NIL(st_table_entry *)) { FREE(new); - return NULL; + return NIL(st_table); } for(i = 0; i < size; i++) { new->bins[i] = 0; @@ -104,7 +85,7 @@ st_table *table; for(i = 0; i < table->num_bins ; i++) { ptr = table->bins[i]; - while (ptr != NULL) { + while (ptr != NIL(st_table_entry)) { next = ptr->next; FREE(ptr); ptr = next; @@ -115,7 +96,7 @@ st_table *table; } #define PTR_NOT_EQUAL(table, ptr, user_key)\ -(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) +(ptr != NIL(st_table_entry) && !EQUAL(table->compare, user_key, (ptr)->key)) #define FIND_ENTRY(table, hash_val, key, ptr, last) \ (last) = &(table)->bins[hash_val];\ @@ -123,7 +104,7 @@ st_table *table; while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ (last) = &(ptr)->next; (ptr) = *(last);\ }\ - if ((ptr) != NULL && (table)->reorder_flag) {\ + if ((ptr) != NIL(st_table_entry) && (table)->reorder_flag) {\ *(last) = (ptr)->next;\ (ptr)->next = (table)->bins[hash_val];\ (table)->bins[hash_val] = (ptr);\ @@ -142,10 +123,10 @@ char **value; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL(st_table_entry)) { return 0; } else { - if (value != NULL) { + if (value != NIL(char *)) { *value = ptr->record; } return 1; @@ -165,10 +146,10 @@ int *value; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL(st_table_entry)) { return 0; } else { - if (value != 0) { + if (value != NIL(int)) { *value = (long) ptr->record; } return 1; @@ -206,7 +187,7 @@ char *value; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL(st_table_entry)) { if (table->num_entries/table->num_bins >= table->max_density) { if (rehash(table) == ST_OUT_OF_MEM) { return ST_OUT_OF_MEM; @@ -214,7 +195,7 @@ char *value; hash_val = do_hash(key, table); } new = ALLOC(st_table_entry, 1); - if (new == NULL) { + if (new == NIL(st_table_entry)) { return ST_OUT_OF_MEM; } new->key = key; @@ -246,7 +227,7 @@ char *value; } hash_val = do_hash(key, table); new = ALLOC(st_table_entry, 1); - if (new == NULL) { + if (new == NIL(st_table_entry)) { return ST_OUT_OF_MEM; } new->key = key; @@ -270,7 +251,7 @@ char ***slot; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL(st_table_entry)) { if (table->num_entries / table->num_bins >= table->max_density) { if (rehash(table) == ST_OUT_OF_MEM) { return ST_OUT_OF_MEM; @@ -278,7 +259,7 @@ char ***slot; hash_val = do_hash(key, table); } new = ALLOC(st_table_entry, 1); - if (new == NULL) { + if (new == NIL(st_table_entry)) { return ST_OUT_OF_MEM; } new->key = key; @@ -286,10 +267,10 @@ char ***slot; new->next = table->bins[hash_val]; table->bins[hash_val] = new; table->num_entries++; - if (slot != NULL) *slot = &new->record; + if (slot != NIL(char **)) *slot = &new->record; return 0; } else { - if (slot != NULL) *slot = &ptr->record; + if (slot != NIL(char **)) *slot = &ptr->record; return 1; } } @@ -307,10 +288,10 @@ char ***slot; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL(st_table_entry)) { return 0; } else { - if (slot != NULL) { + if (slot != NIL(char **)) { *slot = &ptr->record; } return 1; @@ -336,7 +317,7 @@ register st_table *table; } table->num_entries = 0; table->bins = ALLOC(st_table_entry *, table->num_bins); - if (table->bins == NULL) { + if (table->bins == NIL(st_table_entry *)) { table->bins = old_bins; table->num_bins = old_num_bins; table->num_entries = old_num_entries; @@ -350,7 +331,7 @@ register st_table *table; /* copy data over */ for (i = 0; i < old_num_bins; i++) { ptr = old_bins[i]; - while (ptr != NULL) { + while (ptr != NIL(st_table_entry)) { next = ptr->next; hash_val = do_hash(ptr->key, table); ptr->next = table->bins[hash_val]; @@ -373,25 +354,25 @@ st_table *old_table; int i, j, num_bins = old_table->num_bins; new_table = ALLOC(st_table, 1); - if (new_table == NULL) { - return NULL; + if (new_table == NIL(st_table)) { + return NIL(st_table); } *new_table = *old_table; new_table->bins = ALLOC(st_table_entry *, num_bins); - if (new_table->bins == NULL) { + if (new_table->bins == NIL(st_table_entry *)) { FREE(new_table); - return NULL; + return NIL(st_table); } for(i = 0; i < num_bins ; i++) { - new_table->bins[i] = NULL; + new_table->bins[i] = NIL(st_table_entry); ptr = old_table->bins[i]; - while (ptr != NULL) { + while (ptr != NIL(st_table_entry)) { new = ALLOC(st_table_entry, 1); - if (new == NULL) { + if (new == NIL(st_table_entry)) { for (j = 0; j <= i; j++) { newptr = new_table->bins[j]; - while (newptr != NULL) { + while (newptr != NIL(st_table_entry)) { next = newptr->next; FREE(newptr); newptr = next; @@ -399,7 +380,7 @@ st_table *old_table; } FREE(new_table->bins); FREE(new_table); - return NULL; + return NIL(st_table); } *new = *ptr; new->next = new_table->bins[i]; @@ -424,12 +405,12 @@ char **value; FIND_ENTRY(table, hash_val, key, ptr ,last); - if (ptr == NULL) { + if (ptr == NIL(st_table_entry)) { return 0; } *last = ptr->next; - if (value != NULL) *value = ptr->record; + if (value != NIL(char *)) *value = ptr->record; *keyp = ptr->key; FREE(ptr); table->num_entries--; @@ -450,12 +431,12 @@ char **value; FIND_ENTRY(table, hash_val, key, ptr ,last); - if (ptr == NULL) { + if (ptr == NIL(st_table_entry)) { return 0; } *last = ptr->next; - if (value != NULL) *value = ptr->record; + if (value != NIL(char *)) *value = ptr->record; *keyp = (long) ptr->key; FREE(ptr); table->num_entries--; @@ -474,7 +455,7 @@ char *arg; for(i = 0; i < table->num_bins; i++) { last = &table->bins[i]; ptr = *last; - while (ptr != NULL) { + while (ptr != NIL(st_table_entry)) { retval = (*func)(ptr->key, ptr->record, arg); switch (retval) { case ST_CONTINUE: @@ -547,11 +528,11 @@ st_table *table; st_generator *gen; gen = ALLOC(st_generator, 1); - if (gen == NULL) { - return NULL; + if (gen == NIL(st_generator)) { + return NIL(st_generator); } gen->table = table; - gen->entry = NULL; + gen->entry = NIL(st_table_entry); gen->index = 0; return gen; } @@ -565,16 +546,16 @@ char **value_p; { register int i; - if (gen->entry == NULL) { + if (gen->entry == NIL(st_table_entry)) { /* try to find next entry */ for(i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { + if (gen->table->bins[i] != NIL(st_table_entry)) { gen->index = i+1; gen->entry = gen->table->bins[i]; break; } } - if (gen->entry == NULL) { + if (gen->entry == NIL(st_table_entry)) { return 0; /* that's all folks ! */ } } @@ -595,21 +576,21 @@ long *value_p; { register int i; - if (gen->entry == NULL) { + if (gen->entry == NIL(st_table_entry)) { /* try to find next entry */ for(i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { + if (gen->table->bins[i] != NIL(st_table_entry)) { gen->index = i+1; gen->entry = gen->table->bins[i]; break; } } - if (gen->entry == NULL) { + if (gen->entry == NIL(st_table_entry)) { return 0; /* that's all folks ! */ } } *key_p = gen->entry->key; - if (value_p != 0) { + if (value_p != NIL(long)) { *value_p = (long) gen->entry->record; } gen->entry = gen->entry->next; diff --git a/src/misc/st/st.h b/src/misc/st/st.h index b15f3c83..c51873e9 100644 --- a/src/misc/st/st.h +++ b/src/misc/st/st.h @@ -14,10 +14,6 @@ #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; @@ -52,28 +48,28 @@ 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 *); +EXTERN st_table *st_init_table_with_params ARGS((ST_PFI, ST_PFI, int, int, double, int)); +EXTERN st_table *st_init_table ARGS((ST_PFI, ST_PFI)); +EXTERN void st_free_table ARGS((st_table *)); +EXTERN int st_lookup ARGS((st_table *, char *, char **)); +EXTERN int st_lookup_int ARGS((st_table *, char *, int *)); +EXTERN int st_insert ARGS((st_table *, char *, char *)); +EXTERN int st_add_direct ARGS((st_table *, char *, char *)); +EXTERN int st_find_or_add ARGS((st_table *, char *, char ***)); +EXTERN int st_find ARGS((st_table *, char *, char ***)); +EXTERN st_table *st_copy ARGS((st_table *)); +EXTERN int st_delete ARGS((st_table *, char **, char **)); +EXTERN int st_delete_int ARGS((st_table *, long *, char **)); +EXTERN int st_foreach ARGS((st_table *, ST_PFSR, char *)); +EXTERN int st_strhash ARGS((char *, int)); +EXTERN int st_numhash ARGS((char *, int)); +EXTERN int st_ptrhash ARGS((char *, int)); +EXTERN int st_numcmp ARGS((char *, char *)); +EXTERN int st_ptrcmp ARGS((char *, char *)); +EXTERN st_generator *st_init_gen ARGS((st_table *)); +EXTERN int st_gen ARGS((st_generator *, char **, char **)); +EXTERN int st_gen_int ARGS((st_generator *, char **, long *)); +EXTERN void st_free_gen ARGS((st_generator *)); #define ST_DEFAULT_MAX_DENSITY 5 @@ -89,8 +85,4 @@ extern void st_free_gen (st_generator *); #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 index 8dfacfe4..b75b0134 100644 --- a/src/misc/st/stmm.c +++ b/src/misc/st/stmm.c @@ -8,17 +8,12 @@ * */ #include -#include "extra.h" +#include "util.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 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)) @@ -46,8 +41,8 @@ stmm_init_table_with_params (compare, hash, size, density, grow_factor, stmm_table *new; new = ALLOC (stmm_table, 1); - if (new == NULL) { - return NULL; + if (new == NIL (stmm_table)) { + return NIL (stmm_table); } new->compare = compare; new->hash = hash; @@ -60,9 +55,9 @@ stmm_init_table_with_params (compare, hash, size, density, grow_factor, } new->num_bins = size; new->bins = ALLOC (stmm_table_entry *, size); - if (new->bins == NULL) { + if (new->bins == NIL (stmm_table_entry *)) { FREE (new); - return NULL; + return NIL (stmm_table); } for (i = 0; i < size; i++) { new->bins[i] = 0; @@ -95,7 +90,7 @@ stmm_free_table (table) for ( i = 0; i < table->num_bins; i++ ) { ptr = table->bins[i]; - while ( ptr != NULL ) + while ( ptr != NIL( stmm_table_entry ) ) { next = ptr->next; FREE( ptr ); @@ -106,7 +101,7 @@ stmm_free_table (table) // no need to deallocate entries because they are in the memory manager now // added by alanmi if ( table->pMemMan ) - Extra_MmFixedStop (table->pMemMan); + Extra_MmFixedStop (table->pMemMan, 0); FREE (table->bins); FREE (table); } @@ -128,7 +123,7 @@ stmm_clean (table) #define PTR_NOT_EQUAL(table, ptr, user_key)\ -(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) +(ptr != NIL(stmm_table_entry) && !EQUAL(table->compare, user_key, (ptr)->key)) #define FIND_ENTRY(table, hash_val, key, ptr, last) \ (last) = &(table)->bins[hash_val];\ @@ -136,7 +131,7 @@ stmm_clean (table) while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ (last) = &(ptr)->next; (ptr) = *(last);\ }\ - if ((ptr) != NULL && (table)->reorder_flag) {\ + if ((ptr) != NIL(stmm_table_entry) && (table)->reorder_flag) {\ *(last) = (ptr)->next;\ (ptr)->next = (table)->bins[hash_val];\ (table)->bins[hash_val] = (ptr);\ @@ -155,11 +150,11 @@ stmm_lookup (table, key, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL (stmm_table_entry)) { return 0; } else { - if (value != NULL) + if (value != NIL (char *)) { *value = ptr->record; } @@ -180,11 +175,11 @@ stmm_lookup_int (table, key, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL (stmm_table_entry)) { return 0; } else { - if (value != 0) + if (value != NIL (int)) { *value = (long) ptr->record; } @@ -228,7 +223,7 @@ stmm_insert (table, key, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL (stmm_table_entry)) { if (table->num_entries / table->num_bins >= table->max_density) { if (rehash (table) == STMM_OUT_OF_MEM) { return STMM_OUT_OF_MEM; @@ -238,7 +233,7 @@ stmm_insert (table, key, value) // new = ALLOC( stmm_table_entry, 1 ); new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NULL) { + if (new == NIL (stmm_table_entry)) { return STMM_OUT_OF_MEM; } @@ -274,7 +269,7 @@ stmm_add_direct (table, key, value) // new = ALLOC( stmm_table_entry, 1 ); new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NULL) { + if (new == NIL (stmm_table_entry)) { return STMM_OUT_OF_MEM; } @@ -299,7 +294,7 @@ stmm_find_or_add (table, key, slot) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL (stmm_table_entry)) { if (table->num_entries / table->num_bins >= table->max_density) { if (rehash (table) == STMM_OUT_OF_MEM) { return STMM_OUT_OF_MEM; @@ -309,7 +304,7 @@ stmm_find_or_add (table, key, slot) // new = ALLOC( stmm_table_entry, 1 ); new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NULL) { + if (new == NIL (stmm_table_entry)) { return STMM_OUT_OF_MEM; } @@ -318,12 +313,12 @@ stmm_find_or_add (table, key, slot) new->next = table->bins[hash_val]; table->bins[hash_val] = new; table->num_entries++; - if (slot != NULL) + if (slot != NIL (char **)) *slot = &new->record; return 0; } else { - if (slot != NULL) + if (slot != NIL (char **)) *slot = &ptr->record; return 1; } @@ -342,11 +337,11 @@ stmm_find (table, key, slot) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL (stmm_table_entry)) { return 0; } else { - if (slot != NULL) + if (slot != NIL (char **)) { *slot = &ptr->record; } @@ -373,7 +368,7 @@ rehash (table) } table->num_entries = 0; table->bins = ALLOC (stmm_table_entry *, table->num_bins); - if (table->bins == NULL) { + if (table->bins == NIL (stmm_table_entry *)) { table->bins = old_bins; table->num_bins = old_num_bins; table->num_entries = old_num_entries; @@ -387,7 +382,7 @@ rehash (table) /* copy data over */ for (i = 0; i < old_num_bins; i++) { ptr = old_bins[i]; - while (ptr != NULL) { + while (ptr != NIL (stmm_table_entry)) { next = ptr->next; hash_val = do_hash (ptr->key, table); ptr->next = table->bins[hash_val]; @@ -410,15 +405,15 @@ stmm_copy (old_table) int i, /*j, */ num_bins = old_table->num_bins; new_table = ALLOC (stmm_table, 1); - if (new_table == NULL) { - return NULL; + if (new_table == NIL (stmm_table)) { + return NIL (stmm_table); } *new_table = *old_table; new_table->bins = ALLOC (stmm_table_entry *, num_bins); - if (new_table->bins == NULL) { + if (new_table->bins == NIL (stmm_table_entry *)) { FREE (new_table); - return NULL; + return NIL (stmm_table); } // allocate the memory manager for the new table @@ -426,20 +421,20 @@ stmm_copy (old_table) Extra_MmFixedStart (sizeof (stmm_table_entry)); for (i = 0; i < num_bins; i++) { - new_table->bins[i] = NULL; + new_table->bins[i] = NIL (stmm_table_entry); ptr = old_table->bins[i]; - while (ptr != NULL) { + while (ptr != NIL (stmm_table_entry)) { // new = ALLOC( stmm_table_entry, 1 ); new = (stmm_table_entry *) Extra_MmFixedEntryFetch (new_table-> pMemMan); - if (new == NULL) { + if (new == NIL (stmm_table_entry)) { /* for ( j = 0; j <= i; j++ ) { newptr = new_table->bins[j]; - while ( newptr != NULL ) + while ( newptr != NIL( stmm_table_entry ) ) { next = newptr->next; FREE( newptr ); @@ -447,11 +442,11 @@ stmm_copy (old_table) } } */ - Extra_MmFixedStop (new_table->pMemMan); + Extra_MmFixedStop (new_table->pMemMan, 0); FREE (new_table->bins); FREE (new_table); - return NULL; + return NIL (stmm_table); } *new = *ptr; new->next = new_table->bins[i]; @@ -476,12 +471,12 @@ stmm_delete (table, keyp, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL (stmm_table_entry)) { return 0; } *last = ptr->next; - if (value != NULL) + if (value != NIL (char *)) *value = ptr->record; *keyp = ptr->key; // FREE( ptr ); @@ -505,12 +500,12 @@ stmm_delete_int (table, keyp, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NULL) { + if (ptr == NIL (stmm_table_entry)) { return 0; } *last = ptr->next; - if (value != NULL) + if (value != NIL (char *)) *value = ptr->record; *keyp = (long) ptr->key; // FREE( ptr ); @@ -533,7 +528,7 @@ stmm_foreach (table, func, arg) for (i = 0; i < table->num_bins; i++) { last = &table->bins[i]; ptr = *last; - while (ptr != NULL) { + while (ptr != NIL (stmm_table_entry)) { retval = (*func) (ptr->key, ptr->record, arg); switch (retval) { case STMM_CONTINUE: @@ -609,11 +604,11 @@ stmm_init_gen (table) stmm_generator *gen; gen = ALLOC (stmm_generator, 1); - if (gen == NULL) { - return NULL; + if (gen == NIL (stmm_generator)) { + return NIL (stmm_generator); } gen->table = table; - gen->entry = NULL; + gen->entry = NIL (stmm_table_entry); gen->index = 0; return gen; } @@ -627,16 +622,16 @@ stmm_gen (gen, key_p, value_p) { register int i; - if (gen->entry == NULL) { + if (gen->entry == NIL (stmm_table_entry)) { /* try to find next entry */ for (i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { + if (gen->table->bins[i] != NIL (stmm_table_entry)) { gen->index = i + 1; gen->entry = gen->table->bins[i]; break; } } - if (gen->entry == NULL) { + if (gen->entry == NIL (stmm_table_entry)) { return 0; /* that's all folks ! */ } } @@ -657,21 +652,21 @@ stmm_gen_int (gen, key_p, value_p) { register int i; - if (gen->entry == NULL) { + if (gen->entry == NIL (stmm_table_entry)) { /* try to find next entry */ for (i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { + if (gen->table->bins[i] != NIL (stmm_table_entry)) { gen->index = i + 1; gen->entry = gen->table->bins[i]; break; } } - if (gen->entry == NULL) { + if (gen->entry == NIL (stmm_table_entry)) { return 0; /* that's all folks ! */ } } *key_p = gen->entry->key; - if (value_p != 0) + if (value_p != NIL (long)) { *value_p = (long) gen->entry->record; } diff --git a/src/misc/st/stmm.h b/src/misc/st/stmm.h index 4330416e..1fe3dfd2 100644 --- a/src/misc/st/stmm.h +++ b/src/misc/st/stmm.h @@ -14,10 +14,6 @@ #ifndef STMM_INCLUDED #define STMM_INCLUDED -#ifdef __cplusplus -extern "C" { -#endif - #include "extra.h" typedef struct stmm_table_entry stmm_table_entry; @@ -97,7 +93,7 @@ EXTERN void stmm_clean ARGS ((stmm_table *)); // 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; \ + for(gen.table=(tb), gen.entry=NIL(stmm_table_entry), gen.index=0; \ stmm_gen(&(gen),key,value);) #define stmm_foreach_item(table, gen, key, value) \ @@ -120,8 +116,4 @@ EXTERN void stmm_clean ARGS ((stmm_table *)); */ -#ifdef __cplusplus -} -#endif - #endif /* STMM_INCLUDED */ diff --git a/src/misc/util/cpu_stats.c b/src/misc/util/cpu_stats.c new file mode 100644 index 00000000..aa2d18ef --- /dev/null +++ b/src/misc/util/cpu_stats.c @@ -0,0 +1,122 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/util/cpu_stats.c,v + * rajeev + * 1.4 + * 1995/08/08 22:41:17 + * + */ +/* LINTLIBRARY */ + +#include +#include "util.h" + + +#include +//#include +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif + +#if defined(_IBMR2) +#define etext _etext +#define edata _edata +#define end _end +#endif + +#ifndef __CYGWIN32__ +extern int end, etext, edata; +#endif + +void +util_print_cpu_stats(fp) +FILE *fp; +{ + (void) fprintf(fp, "Usage statistics not available\n"); +} + +#if 0 + +void +util_print_cpu_stats(fp) +FILE *fp; +{ +#if HAVE_SYS_RESOURCE_H && !defined(__CYGWIN32__) + struct rusage rusage; +#ifdef RLIMIT_DATA + struct rlimit rlp; +#endif + int text, data, vm_limit, vm_soft_limit; + double user, system, scale; + char hostname[257]; + int vm_text, vm_init_data, vm_uninit_data, vm_sbrk_data; + + /* Get the hostname */ + (void) gethostname(hostname, 256); + hostname[256] = '\0'; /* just in case */ + + /* Get the virtual memory sizes */ + vm_text = ((int) (&etext)) / 1024.0 + 0.5; + vm_init_data = ((int) (&edata) - (int) (&etext)) / 1024.0 + 0.5; + vm_uninit_data = ((int) (&end) - (int) (&edata)) / 1024.0 + 0.5; + vm_sbrk_data = (sizeof(char) * ((char *) sbrk(0) - (char *) (&end))) / 1024.0 + 0.5; + + /* Get virtual memory limits */ +#ifdef RLIMIT_DATA /* In HP-UX, with cc, this constant does not exist */ + (void) getrlimit(RLIMIT_DATA, &rlp); + vm_limit = rlp.rlim_max / 1024.0 + 0.5; + vm_soft_limit = rlp.rlim_cur / 1024.0 + 0.5; +#else + vm_limit = -1; + vm_soft_limit = -1; +#endif + + /* Get usage stats */ + (void) getrusage(RUSAGE_SELF, &rusage); + user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec/1.0e6; + system = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec/1.0e6; + scale = (user + system)*100.0; + if (scale == 0.0) scale = 0.001; + + (void) fprintf(fp, "Runtime Statistics\n"); + (void) fprintf(fp, "------------------\n"); + (void) fprintf(fp, "Machine name: %s\n", hostname); + (void) fprintf(fp, "User time %6.1f seconds\n", user); + (void) fprintf(fp, "System time %6.1f seconds\n\n", system); + + text = rusage.ru_ixrss / scale + 0.5; + data = (rusage.ru_idrss + rusage.ru_isrss) / scale + 0.5; + (void) fprintf(fp, "Average resident text size = %5dK\n", text); + (void) fprintf(fp, "Average resident data+stack size = %5dK\n", data); + (void) fprintf(fp, "Maximum resident size = %5ldK\n\n", + rusage.ru_maxrss/2); + (void) fprintf(fp, "Virtual text size = %5dK\n", + vm_text); + (void) fprintf(fp, "Virtual data size = %5dK\n", + vm_init_data + vm_uninit_data + vm_sbrk_data); + (void) fprintf(fp, " data size initialized = %5dK\n", + vm_init_data); + (void) fprintf(fp, " data size uninitialized = %5dK\n", + vm_uninit_data); + (void) fprintf(fp, " data size sbrk = %5dK\n", + vm_sbrk_data); + /* In some platforms, this constant does not exist */ +#ifdef RLIMIT_DATA + (void) fprintf(fp, "Virtual memory limit = %5dK (%dK)\n\n", + vm_soft_limit, vm_limit); +#endif + (void) fprintf(fp, "Major page faults = %ld\n", rusage.ru_majflt); + (void) fprintf(fp, "Minor page faults = %ld\n", rusage.ru_minflt); + (void) fprintf(fp, "Swaps = %ld\n", rusage.ru_nswap); + (void) fprintf(fp, "Input blocks = %ld\n", rusage.ru_inblock); + (void) fprintf(fp, "Output blocks = %ld\n", rusage.ru_oublock); + (void) fprintf(fp, "Context switch (voluntary) = %ld\n", rusage.ru_nvcsw); + (void) fprintf(fp, "Context switch (involuntary) = %ld\n", rusage.ru_nivcsw); +#else /* Do not have sys/resource.h */ + (void) fprintf(fp, "Usage statistics not available\n"); +#endif +} + +#endif + diff --git a/src/misc/util/cpu_time.c b/src/misc/util/cpu_time.c new file mode 100644 index 00000000..d264bdc9 --- /dev/null +++ b/src/misc/util/cpu_time.c @@ -0,0 +1,128 @@ +/**CFile*********************************************************************** + + FileName [ cpu_time.c ] + + PackageName [ util ] + + Synopsis [ System time calls ] + + Description [ The problem is that all unix systems have a different notion + of how fast time goes (i.e., the units returned by). This + returns a consistent result. ] + + Author [ Stephen Edwards and others ] + + Copyright [Copyright (c) 1994-1996 The Regents of the Univ. 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.] + +******************************************************************************/ + +#include "util.h" + +#if HAVE_SYS_TYPES_H +# include +#endif + +#if HAVE_SYS_TIMES_H +# include +#endif + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/**Function******************************************************************** + + Synopsis [ Return elapsed time in milliseconds ] + + Description [ Return a long which represents the elapsed time in + milliseconds since some constant reference.

+ + There are two possibilities: +

    +
  1. The system is non-POSIX compliant, so unistd.h + and hence sysconf() can't tell us the clock tick + speed. At this point, we have to resort to + using the user-settable CLOCK_RESOLUTION definition + to get the right speed +
  2. The system is POSIX-compliant. unistd.h gives + us sysconf(), which tells us the clock rate. +
+ ] + + SideEffects [ none ] + +******************************************************************************/ + +/* +long +util_cpu_time() +{ + long t = 0; + +#if HAVE_SYSCONF == 1 + + // Code for POSIX systems + + struct tms buffer; + long nticks; // number of clock ticks per second + + nticks = sysconf(_SC_CLK_TCK); + times(&buffer); + t = buffer.tms_utime * (1000.0/nticks); + +#else +# ifndef vms + + // Code for non-POSIX systems + + struct tms buffer; + + time(&buffer); + t = buffer.tms_utime * 1000.0 / CLOCK_RESOLUTION; + +# else + + // Code for VMS (?) + + struct {int p1, p2, p3, p4;} buffer; + static long ref_time; + times(&buffer); + t = buffer.p1 * 10; + if (ref_time == 0) + ref_time = t; + t = t - ref_time; + +# endif // vms +#endif // _POSIX_VERSION + + return t; +} +*/ + + +long +util_cpu_time() +{ + return clock(); +} diff --git a/src/misc/util/datalimit.c b/src/misc/util/datalimit.c new file mode 100644 index 00000000..96c2ce95 --- /dev/null +++ b/src/misc/util/datalimit.c @@ -0,0 +1,95 @@ +/**CFile************************************************************************ + + FileName [datalimit.c] + + PackageName [util] + + Synopsis [Routine to obtain the maximum data size available to a program. The + routine is based on "getrlimit". If the system does not have this function, + the default value RLIMIT_DATA_DEFAULT is assumed. This function provides an + informative value, it does not restrict the size of the program in any way.] + + 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.h" + +static char rcsid[] UNUSED = "$Id: datalimit.c,v 1.1.1.1 2003/02/24 22:24:04 wjiang Exp $"; + +#if HAVE_SYS_RESOURCE_H +#if HAVE_SYS_TIME_H +#include +#endif +#include +#endif + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef RLIMIT_DATA_DEFAULT +#define RLIMIT_DATA_DEFAULT 67108864 /* assume 64MB by default */ +#endif + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Function that computes the data limit of the process.] + + SideEffects [] + +******************************************************************************/ +int +getSoftDataLimit() +{ +#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && defined(RLIMIT_DATA) + struct rlimit rl; + int result; + + result = getrlimit(RLIMIT_DATA, &rl); + if (result != 0 || rl.rlim_cur == RLIM_INFINITY) + return(RLIMIT_DATA_DEFAULT); + else + return(rl.rlim_cur); +#else + return(RLIMIT_DATA_DEFAULT); +#endif + +} /* end of getSoftDataLimit */ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ diff --git a/src/misc/util/getopt.c b/src/misc/util/getopt.c new file mode 100644 index 00000000..778c34d6 --- /dev/null +++ b/src/misc/util/getopt.c @@ -0,0 +1,84 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/util/getopt.c,v + * rajeev + * 1.3 + * 1995/08/08 22:41:22 + * + */ +/* LINTLIBRARY */ + +#include +#include "util.h" + + +/* 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 *util_optarg; /* Global argument pointer. */ +int util_optind = 0; /* Global argv index. */ +static char *scan; + + +void +util_getopt_reset() +{ + util_optarg = 0; + util_optind = 0; + scan = 0; +} + + + +int +util_getopt(argc, argv, optstring) +int argc; +char *argv[]; +char *optstring; +{ + register int c; + register char *place; + + util_optarg = NIL(char); + + if (scan == NIL(char) || *scan == '\0') { + if (util_optind == 0) util_optind++; + if (util_optind >= argc) return EOF; + place = argv[util_optind]; + if (place[0] != '-' || place[1] == '\0') return EOF; + util_optind++; + if (place[1] == '-' && place[2] == '\0') return EOF; + scan = place+1; + } + + c = *scan++; + place = strchr(optstring, c); + if (place == NIL(char) || c == ':') { + (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c); + return '?'; + } + if (*++place == ':') { + if (*scan != '\0') { + util_optarg = scan; + scan = NIL(char); + } else { + if (util_optind >= argc) { + (void) fprintf(stderr, "%s: %c requires an argument\n", + argv[0], c); + return '?'; + } + util_optarg = argv[util_optind]; + util_optind++; + } + } + return c; +} diff --git a/src/misc/util/leaks.h b/src/misc/util/leaks.h index 1a32062a..daa628b1 100644 --- a/src/misc/util/leaks.h +++ b/src/misc/util/leaks.h @@ -1,8 +1,8 @@ -////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// // 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" -////////////////////////////////////////////////////////////////////////// +// The idea comes from the following webpage: +// http://www.michaelmoser.org/memory.htm +////////////////////////////////////// #ifndef __LEAKS_H__ #define __LEAKS_H__ diff --git a/src/misc/util/module.make b/src/misc/util/module.make index d6d908e7..06eba7e4 100644 --- a/src/misc/util/module.make +++ b/src/misc/util/module.make @@ -1 +1,8 @@ -SRC += +SRC += src/misc/util/cpu_stats.c \ + src/misc/util/cpu_time.c \ + src/misc/util/datalimit.c \ + src/misc/util/getopt.c \ + src/misc/util/pathsearch.c \ + src/misc/util/safe_mem.c \ + src/misc/util/strsav.c \ + src/misc/util/texpand.c diff --git a/src/misc/util/pathsearch.c b/src/misc/util/pathsearch.c new file mode 100644 index 00000000..d4d845eb --- /dev/null +++ b/src/misc/util/pathsearch.c @@ -0,0 +1,131 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/util/pathsearch.c,v + * rajeev + * 1.3 + * 1995/08/08 22:41:24 + * + */ +/* LINTLIBRARY */ + +#if HAVE_SYS_FILE_H +# include +#endif + +#if HAVE_SYS_STAT_H +# include +#endif + +#include "util.h" + +/**Function******************************************************************** + + Synopsis [ Check that a given file is present and accessible ] + + SideEffects [none] +******************************************************************************/ +static int +check_file(filename, mode) +char *filename; +char *mode; +{ +#if defined(HAVE_SYS_STAT_H) + struct stat stat_rec; + int access_char = mode[0]; + int access_mode = R_OK; + + /* First check that the file is a regular file. */ + + if (stat(filename,&stat_rec) == 0 + && (stat_rec.st_mode&S_IFMT) == S_IFREG) { + if (access_char == 'w') { + access_mode = W_OK; + } else if (access_char == 'x') { + access_mode = X_OK; + } + return access(filename,access_mode) == 0; + } + return 0; + +#else + + 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; + +#endif +} + +/**Function******************************************************************** + + Synopsis [ Search for a program in all possible paths ] + + SideEffects [none] + +******************************************************************************/ +char * +util_path_search(prog) +char *prog; +{ +#ifdef HAVE_GETENV + return util_file_search(prog, getenv("PATH"), "x"); +#else + return util_file_search(prog, NIL(char), "x"); +#endif +} + +char * +util_file_search(file, path, 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 = util_strsav(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 = util_strsav(file); + } else { + buffer = ALLOC(char, strlen(path) + strlen(file) + 4); + (void) sprintf(buffer, "%s/%s", path, file); + } + filename = util_tilde_expand(buffer); + FREE(buffer); + + /* see if we can access it */ + if (check_file(filename, mode)) { + FREE(save_path); + return filename; + } + FREE(filename); + path = ++cp; + } while (! quit); + + FREE(save_path); + return 0; +} diff --git a/src/misc/util/safe_mem.c b/src/misc/util/safe_mem.c new file mode 100644 index 00000000..5a8a5de8 --- /dev/null +++ b/src/misc/util/safe_mem.c @@ -0,0 +1,104 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/util/safe_mem.c,v + * rajeev + * 1.3 + * 1995/08/08 22:41:29 + * + */ +/* LINTLIBRARY */ + +#include "util.h" + +/* + * These are interface routines to be placed between a program and the + * system memory allocator. + * + * It forces well-defined semantics for several 'borderline' cases: + * + * malloc() of a 0 size object is guaranteed to return something + * which is not 0, and can safely be freed (but not dereferenced) + * free() accepts (silently) an 0 pointer + * realloc of a 0 pointer is allowed, and is equiv. to malloc() + * For the IBM/PC it forces no object > 64K; note that the size argument + * to malloc/realloc is a 'long' to catch this condition + * + * The function pointer MMoutOfMemory() contains a vector to handle a + * 'out-of-memory' error (which, by default, points at a simple wrap-up + * and exit routine). + */ + +extern char *MMalloc(); +extern void MMout_of_memory(); +extern char *MMrealloc(); + + +void (*MMoutOfMemory)() = MMout_of_memory; + + +/* MMout_of_memory -- out of memory for lazy people, flush and exit */ +void +MMout_of_memory(size) +long size; +{ + (void) fflush(stdout); + (void) fprintf(stderr, "\nout of memory allocating %u bytes\n", + (unsigned) size); + assert( 0 ); + exit(1); +} + + +char * +MMalloc(size) +long size; +{ + char *p; + +#ifdef IBMPC + if (size > 65000L) { + if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size); + return NIL(char); + } +#endif + if (size == 0) size = sizeof(long); + if ((p = (char *) malloc((unsigned) size)) == NIL(char)) { + if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size); + return NIL(char); + } + return p; +} + + +char * +MMrealloc(obj, size) +char *obj; +long size; +{ + char *p; + +#ifdef IBMPC + if (size > 65000L) { + if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size); + return NIL(char); + } +#endif + if (obj == NIL(char)) return MMalloc(size); + if (size <= 0) size = sizeof(long); + if ((p = (char *) realloc(obj, (unsigned) size)) == NIL(char)) { + if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size); + return NIL(char); + } + return p; +} + + +void +MMfree(obj) +char *obj; +{ + if (obj != 0) { + free(obj); + } +} diff --git a/src/misc/util/strsav.c b/src/misc/util/strsav.c new file mode 100644 index 00000000..8da1f0c9 --- /dev/null +++ b/src/misc/util/strsav.c @@ -0,0 +1,157 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/util/strsav.c,v + * shiple + * 1.4 + * 1995/08/30 17:37:58 + * + */ +/* LINTLIBRARY */ + +#include +#include "util.h" + + +/* + * util_strsav -- save a copy of a string + */ +char * +util_strsav(s) +char *s; +{ + if(s == NIL(char)) { /* added 7/95, for robustness */ + return s; + } + else { + return strcpy(ALLOC(char, strlen(s)+1), s); + } +} + +/* + * util_inttostr -- converts an integer into a string + */ +char * +util_inttostr(i) + int i; +{ + unsigned int mod, len; + char *s; + + if (i == 0) + len = 1; + else { + if (i < 0) { + len = 1; + mod = -i; + } + else { + len = 0; + mod = i; + } + len += (unsigned)floor(log10(mod)) + 1; + } + + s = ALLOC(char, len + 1); + sprintf(s, "%d", i); + + return s; +} + +/* + * util_strcat3 -- Creates a new string which is the concatenation of 3 + * strings. It is the responsibility of the caller to free this string + * using FREE. + */ +char * +util_strcat3( + char * str1, + char * str2, + char * str3) +{ + char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) + 1); + + (void) strcpy(str, str1); + (void) strcat(str, str2); + (void) strcat(str, str3); + + return (str); +} + +/* + * util_strcat4 -- Creates a new string which is the concatenation of 4 + * strings. It is the responsibility of the caller to free this string + * using FREE. + */ +char * +util_strcat4( + char * str1, + char * str2, + char * str3, + char * str4) +{ + char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) + + strlen(str4) + 1); + + (void) strcpy(str, str1); + (void) strcat(str, str2); + (void) strcat(str, str3); + (void) strcat(str, str4); + + return (str); +} + + +#if !HAVE_STRSTR +/**Function******************************************************************** + + Synopsis [required] + + Description [optional] + + SideEffects [required] + + SeeAlso [optional] + +******************************************************************************/ +char * +strstr( + const char * s, + const char * pat) +{ + int len; + + len = strlen(pat); + for (; *s != '\0'; ++s) + if (*s == *pat && memcmp(s, pat, len) == 0) { + return (char *)s; /* UGH */ + } + return NULL; +} +#endif /* !HAVE_STRSTR */ + +#if !HAVE_STRCHR +/**Function******************************************************************** + + Synopsis [required] + + Description [optional] + + SideEffects [required] + + SeeAlso [optional] + +******************************************************************************/ +char * +strchr(const char * s, + int c) +{ + for (; *s != '\0'; s++) { + if (*s == c) { + return (char *)s; + } + } + return NULL; + +} +#endif /* !HAVE_STRCHR */ diff --git a/src/misc/util/texpand.c b/src/misc/util/texpand.c new file mode 100644 index 00000000..37f71cbd --- /dev/null +++ b/src/misc/util/texpand.c @@ -0,0 +1,66 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/util/texpand.c,v + * rajeev + * 1.3 + * 1995/08/08 22:41:36 + * + */ + +#include "util.h" + +#if HAVE_PWD_H +# include +#endif + + +char * +util_tilde_expand(fname) +char *fname; +{ +#if HAVE_PWD_H + struct passwd *userRecord; + char username[256], *filename, *dir; + register int i, j; + + filename = ALLOC(char, strlen(fname) + 256); + + /* Clear the return string */ + i = 0; + filename[0] = '\0'; + + /* Tilde? */ + if (fname[0] == '~') { + j = 0; + i = 1; + while ((fname[i] != '\0') && (fname[i] != '/')) { + username[j++] = fname[i++]; + } + username[j] = '\0'; + dir = (char *)0; + if (username[0] == '\0') { + /* ~/ resolves to home directory of current user */ + userRecord = getpwuid(getuid()); + if (userRecord) dir = userRecord->pw_dir; + } else { + /* Special check for ~octtools */ + if (!strcmp(username,"octtools")) + dir = getenv("OCTTOOLS"); + /* ~user/ resolves to home directory of 'user' */ + if (!dir) { + userRecord = getpwnam(username); + if (userRecord) dir = userRecord->pw_dir; + } + } + if (dir) (void) strcat(filename, dir); + else i = 0; /* leave fname as-is */ + } /* if tilde */ + + /* Concantenate remaining portion of file name */ + (void) strcat(filename, fname + i); + return filename; +#else + return util_strsav(fname); +#endif +} diff --git a/src/misc/util/util.h b/src/misc/util/util.h new file mode 100644 index 00000000..0b147347 --- /dev/null +++ b/src/misc/util/util.h @@ -0,0 +1,331 @@ +/**CHeaderFile***************************************************************** + + FileName [ util.h ] + + PackageName [ util ] + + Synopsis [ Very low-level utilities ] + + Description [ Includes file access, pipes, forks, time, and temporary file + access. ] + + Author [ Stephen Edwards and many others] + + Copyright [Copyright (c) 1994-1996 The Regents of the Univ. 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.] + + Revision [$Id: util.h,v 1.11 1998/05/04 02:05:08 hsv Exp $] + +******************************************************************************/ + +#ifndef _UTIL +#define _UTIL + +//////////////////////////////////////////// +#include "leaks.h" +//////////////////////////////////////////// + +#include +#include +#include + +//////////////// added by alanmi, November 22, 2001 //////////////// +//#include +#include +#include + +#ifndef SIGALRM +#define SIGALRM SIGINT +#endif + +#ifndef SIGSTOP +#define SIGSTOP SIGINT +#endif + +#ifndef SIGXCPU +#define SIGXCPU SIGINT +#endif + +#ifndef SIGUSR1 +#define SIGUSR1 SIGINT +#endif + +#ifndef SIGKILL +#define SIGKILL SIGINT +#endif + +#ifndef HUGE +#define HUGE HUGE_VAL +#endif + +#if defined(__STDC__) +#define SIGNAL_FN void +#endif + +#define alarm(n) ((void)0) +#define kill(a,b) ((void)0) + +#define random rand +#define srandom srand +//////////////////////////////////////////////////////////////////// + + +#if HAVE_UNISTD_H +# include +#endif + +#if HAVE_SYS_TYPES_H +# include +#endif + +#if HAVE_VARARGS_H +/////////////////////////////////////// +#undef __STDC__ +# include +#define __STDC__ 1 +////////////////// alanmi Feb 03, 2001 +#endif + +#ifndef STDC_HEADERS +#define STDC_HEADERS 1 +#endif + +#ifndef HAVE_STRCHR +#define HAVE_STRCHR 1 +#endif + +#ifndef HAVE_GETENV +#define HAVE_GETENV 1 +#endif + +#if STDC_HEADERS +//# include +# include +#else +# ifdef HAVE_STRCHR +char * strchr(); +int strcmp(); +# else +# define strchr index +# endif +# ifdef HAVE_GETENV +char * getenv(); +# endif +#endif /* STDC_HEADERS */ + +#if HAVE_ERRNO_H +# include +#endif + +/* + * Ensure we have reasonable assert() and fail() functions + */ + +#ifndef HAVE_ASSERT_H +#define HAVE_ASSERT_H 1 +#endif + +#if HAVE_ASSERT_H +# include +#else +# ifdef NDEBUG +# define assert(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 +#endif + +#define fail(why) {\ + (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ + __FILE__, __LINE__, why);\ + (void) fflush(stdout);\ + abort();\ +} + +/* + * Support for ANSI function prototypes in non-ANSI compilers + * + * Usage: + * extern int foo ARGS((char *, double)) + */ + +#ifndef ARGS +# ifdef __STDC__ +# define ARGS(args) args +# else +# define ARGS(args) () +# endif +#endif + +#ifndef NULLARGS +# ifdef __STDC__ +# define NULLARGS (void) +# else +# define NULLARGS () +# endif +#endif + +/* + * A little support for C++ compilers + */ + +#ifdef __cplusplus +# define EXTERN extern "C" +#else +# define EXTERN extern +#endif + +/* + * Support to define unused varibles + */ +#if (__GNUC__ >2 || __GNUC_MINOR__ >=7) && !defined(UNUSED) +#define UNUSED __attribute__ ((unused)) +#else +#define UNUSED +#endif + +/* + * A neater way to define zero pointers + * + * Usage: + * int * fred; + * fred = NIL(int); + */ + +#define NIL(type) ((type *) 0) + +/* + * Left over from SIS and Octtools: + */ + +//#define USE_MM +// uncommented this line, +// because to detect memory leaks, we need to work with malloc(), etc directly +#define USE_MM + + + +#ifdef USE_MM +/* + * assumes the memory manager is libmm.a (a deprecated (?) Octtools library) + * - 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 + */ +# 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) +EXTERN void MMout_of_memory ARGS((long)); +EXTERN char *MMalloc ARGS((long)); +EXTERN char *MMrealloc ARGS((char *, long)); +EXTERN void MMfree ARGS((char *)); +#endif + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#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 ptime() util_cpu_time() +#define print_time(t) util_print_time(t) + +#ifndef HUGE_VAL +# ifndef HUGE +# define HUGE 8.9884656743115790e+307 +# endif +# define HUGE_VAL HUGE +#endif + +#ifndef MAXINT +# define MAXINT (1 << 30) +#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 char *util_print_time ARGS((long)); +EXTERN int util_save_image ARGS((char *, char *)); +EXTERN char *util_strsav ARGS((char *)); +EXTERN char *util_inttostr ARGS((int)); +EXTERN char *util_strcat3 ARGS((char *, char *, char *)); +EXTERN char *util_strcat4 ARGS((char *, char *, char *, 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 void util_srandom ARGS((long)); +EXTERN long util_random ARGS(()); +EXTERN int getSoftDataLimit ARGS(()); + +/* + * Global variables for util_getopt() + */ + +extern int util_optind; +extern char *util_optarg; + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +#endif /* _UTIL */ 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/vec.h b/src/misc/vec/vec.h index a4bd4771..48c4b3c3 100644 --- a/src/misc/vec/vec.h +++ b/src/misc/vec/vec.h @@ -21,81 +21,19 @@ #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 - -#ifndef SINT64 -#define SINT64 - -#ifdef _WIN32 -typedef signed __int64 sint64; // compatible with MS VS 6.0 -#else -typedef long long sint64; -#endif - -#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) +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 #endif +#include "vecFan.h" #include "vecInt.h" -#include "vecFlt.h" #include "vecStr.h" #include "vecPtr.h" #include "vecVec.h" -#include "vecAtt.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -106,16 +44,16 @@ typedef long long sint64; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// -#ifdef __cplusplus -} -#endif - -#endif +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + 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/vecFan.h b/src/misc/vec/vecFan.h new file mode 100644 index 00000000..08d1d734 --- /dev/null +++ b/src/misc/vec/vecFan.h @@ -0,0 +1,374 @@ +/**CFile**************************************************************** + + FileName [vecFan.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [Resizable arrays of integers (fanins/fanouts) with memory management.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vecFan.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VEC_FAN_H__ +#define __VEC_FAN_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_Fan_t_ Abc_Fan_t; +struct Abc_Fan_t_ // 1 word +{ + unsigned iFan : 24; // the ID of the object + unsigned nLats : 7; // the number of latches (up to 31) + unsigned fCompl : 1; // the complemented attribute +}; + +typedef struct Vec_Fan_t_ Vec_Fan_t; +struct Vec_Fan_t_ +{ + int nCap; + int nSize; + Abc_Fan_t * pArray; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Vec_FanForEachEntry( vVec, Entry, i ) \ + for ( i = 0; (i < Vec_FanSize(vVec)) && (((Entry) = Vec_FanEntry(vVec, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts an integer into the simple fanin structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Fan_t Vec_Int2Fan( int iFan ) +{ + return *((Abc_Fan_t *)&iFan); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Fan_t * Vec_FanArray( Vec_Fan_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FanSize( Vec_Fan_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Fan_t Vec_FanEntry( Vec_Fan_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FanWriteEntry( Vec_Fan_t * p, int i, Abc_Fan_t Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Fan_t Vec_FanEntryLast( Vec_Fan_t * p ) +{ + return p->pArray[p->nSize-1]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FanShrink( Vec_Fan_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FanClear( Vec_Fan_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FanPush( Extra_MmStep_t * pMemMan, Vec_Fan_t * p, Abc_Fan_t Entry ) +{ + if ( p->nSize == p->nCap ) + { + Abc_Fan_t * pArray; + int i; + + if ( p->nSize == 0 ) + p->nCap = 1; + pArray = (Abc_Fan_t *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 ); +// pArray = ALLOC( int, p->nCap * 2 ); + if ( p->pArray ) + { + for ( i = 0; i < p->nSize; i++ ) + pArray[i] = p->pArray[i]; + Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 ); +// free( p->pArray ); + } + p->nCap *= 2; + p->pArray = pArray; + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Returns the last entry and removes it from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Fan_t Vec_FanPop( Vec_Fan_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [Find entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FanFindEntry( Vec_Fan_t * p, unsigned iFan ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i].iFan == iFan ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Deletes entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FanDeleteEntry( Vec_Fan_t * p, unsigned iFan ) +{ +/* + int i, k, fFound = 0; + for ( i = k = 0; i < p->nSize; i++ ) + { + if ( p->pArray[i].iFan == iFan ) + fFound = 1; + else + p->pArray[k++] = p->pArray[i]; + } + p->nSize = k; + return fFound; +*/ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i].iFan == iFan ) + break; + if ( i == p->nSize ) + return 0; + 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_FanSortCompare1( 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_FanSortCompare2( 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_FanSort( Vec_Fan_t * p, int fReverse ) +{ + if ( fReverse ) + qsort( (void *)p->pArray, p->nSize, sizeof(int), + (int (*)(const void *, const void *)) Vec_FanSortCompare2 ); + else + qsort( (void *)p->pArray, p->nSize, sizeof(int), + (int (*)(const void *, const void *)) Vec_FanSortCompare1 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + 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 index 082ebe70..7556dd87 100644 --- a/src/misc/vec/vecInt.h +++ b/src/misc/vec/vecInt.h @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////// #include +#include "extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -44,20 +45,16 @@ struct Vec_Int_t_ }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// #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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -103,28 +100,6 @@ static inline Vec_Int_t * Vec_IntStart( 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.] @@ -184,7 +159,7 @@ 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->nCap = pVec->nCap; p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize ); return p; @@ -317,23 +292,6 @@ static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry ) 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 [] @@ -347,7 +305,6 @@ static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition ) ***********************************************************************/ static inline int Vec_IntEntryLast( Vec_Int_t * p ) { - assert( p->nSize > 0 ); return p->pArray[p->nSize-1]; } @@ -367,7 +324,6 @@ 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; } @@ -479,33 +435,6 @@ static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) 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 ) { @@ -526,27 +455,6 @@ static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry ) 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 [] @@ -568,31 +476,6 @@ static inline int Vec_IntPushUnique( Vec_Int_t * p, int 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.] @@ -610,26 +493,6 @@ static inline int Vec_IntPop( Vec_Int_t * p ) 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 [] @@ -641,19 +504,16 @@ static inline int Vec_IntFind( Vec_Int_t * p, int Entry ) SeeAlso [] ***********************************************************************/ -static inline int Vec_IntRemove( Vec_Int_t * p, int Entry ) +static inline void 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************************************************************* @@ -757,78 +617,9 @@ static inline void Vec_IntSortUnsigned( Vec_Int_t * p ) (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 /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/misc/vec/vecPtr.h b/src/misc/vec/vecPtr.h index 9595bc72..b1776441 100644 --- a/src/misc/vec/vecPtr.h +++ b/src/misc/vec/vecPtr.h @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////// #include +#include "extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -44,7 +45,7 @@ struct Vec_Ptr_t_ }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // iterators through entries @@ -52,15 +53,11 @@ struct Vec_Ptr_t_ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -281,23 +278,6 @@ static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i ) return p->pArray[i]; } -/**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 [] @@ -328,7 +308,6 @@ static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry ) ***********************************************************************/ static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p ) { - assert( p->nSize > 0 ); return p->pArray[p->nSize-1]; } @@ -387,50 +366,12 @@ 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 ); + 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 [] @@ -464,25 +405,6 @@ 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 [] @@ -544,26 +466,6 @@ static inline void * Vec_PtrPop( Vec_Ptr_t * p ) 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 [] @@ -578,18 +480,10 @@ static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry ) 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--; @@ -627,186 +521,14 @@ static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems ) ***********************************************************************/ 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; -} - - - -/**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 [Cleans simulation info of each entry beginning with iWord.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrCleanSimInfo( Vec_Ptr_t * vInfo, int iWord, int nWords ) -{ - int i; - for ( i = 0; i < vInfo->nSize; i++ ) - memset( (char*)Vec_PtrEntry(vInfo,i) + 4*iWord, 0, 4*(nWords-iWord) ); -} - -/**Function************************************************************* - - Synopsis [Resizes the array of simulation info.] - - Description [Doubles the number of objects for which siminfo is allocated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo ) -{ - Vec_Ptr_t * vInfoNew; - int nWords; - assert( Vec_PtrSize(vInfo) > 1 ); - // 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 [Resizes the array of simulation info.] - - Description [Doubles the number of simulation patterns stored for each object.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrReallocSimInfo( Vec_Ptr_t * vInfo ) -{ - Vec_Ptr_t * vInfoNew; - int nWords, i; - assert( Vec_PtrSize(vInfo) > 1 ); - // get the new array - nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0); - vInfoNew = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), 2*nWords ); - // copy the simulation info - for ( i = 0; i < vInfo->nSize; i++ ) - memcpy( Vec_PtrEntry(vInfoNew,i), Vec_PtrEntry(vInfo,i), nWords * 4 ); - // replace the array - free( vInfo->pArray ); - vInfo->pArray = vInfoNew->pArray; - // free the old array - vInfoNew->pArray = NULL; - free( vInfoNew ); -} - -/**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; -} - -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/misc/vec/vecStr.h b/src/misc/vec/vecStr.h index 47367bc6..311bda91 100644 --- a/src/misc/vec/vecStr.h +++ b/src/misc/vec/vecStr.h @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////// #include +#include "extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -44,14 +45,14 @@ struct Vec_Str_t_ }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// #define Vec_StrForEachEntry( vVec, Entry, i ) \ for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -302,7 +303,6 @@ static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry ) ***********************************************************************/ static inline char Vec_StrEntryLast( Vec_Str_t * p ) { - assert( p->nSize > 0 ); return p->pArray[p->nSize-1]; } @@ -401,80 +401,6 @@ static inline void Vec_StrPush( Vec_Str_t * p, char Entry ) 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.] @@ -568,16 +494,16 @@ static inline int Vec_StrSortCompare2( char * pp1, char * pp2 ) static inline void Vec_StrSort( Vec_Str_t * p, int fReverse ) { if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(char), + qsort( (void *)p->pArray, p->nSize, sizeof(int), (int (*)(const void *, const void *)) Vec_StrSortCompare2 ); else - qsort( (void *)p->pArray, p->nSize, sizeof(char), + qsort( (void *)p->pArray, p->nSize, sizeof(int), (int (*)(const void *, const void *)) Vec_StrSortCompare1 ); } -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/misc/vec/vecVec.h b/src/misc/vec/vecVec.h index 55ffdf4f..0ad5fd1e 100644 --- a/src/misc/vec/vecVec.h +++ b/src/misc/vec/vecVec.h @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////// #include +#include "extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -44,27 +45,23 @@ struct Vec_Vec_t_ }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // 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++ ) + for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = 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++ ) + for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = 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++ ) + for ( i = LevelStart; (i <= LevelStop) && (((vVec) = 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-- ) + for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = 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 ) @@ -74,15 +71,9 @@ struct Vec_Vec_t_ #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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -130,28 +121,6 @@ static inline Vec_Vec_t * Vec_VecStart( int 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 [] @@ -265,7 +234,7 @@ static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry ) p->pArray[i] = Vec_PtrAlloc( 0 ); p->nSize = Level + 1; } - Vec_PtrPush( (Vec_Ptr_t*)p->pArray[Level], Entry ); + Vec_PtrPush( p->pArray[Level], Entry ); } /**Function************************************************************* @@ -284,73 +253,12 @@ 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 ); + Vec_PtrPushUnique( p->pArray[Level], Entry ); } -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + 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 index dee05dfc..6719ed4d 100644 --- a/src/opt/cut/cut.h +++ b/src/opt/cut/cut.h @@ -21,10 +21,6 @@ #ifndef __CUT_H__ #define __CUT_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -33,133 +29,81 @@ extern "C" { /// 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 + 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 fTruth; // compute truth tables + int fHash; // hash cuts to detect unique + int fFilter; // filter dominated cuts + int fSeq; // compute sequential cuts + int fDrop; // drop cuts on the fly + int fVerbose; // the verbosiness flag }; struct Cut_CutStruct_t_ { - unsigned Num0 : 11; // temporary number - unsigned Num1 : 11; // temporary number + unsigned uTruth : 16; // truth table for 4-input cuts + unsigned uPhase : 7; // the phase when mapping into a canonical form 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 + unsigned fSeq : 1; // the cut is sequential + unsigned nVarsMax : 3; // the max number of vars [4-6] + unsigned nLeaves : 3; // the number of leaves [4-6] Cut_Cut_t * pNext; // the next cut in the list + void * pData; // the user data int pLeaves[0]; // the array of leaves }; +static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p ) { if ( p->nVarsMax == 4 ) return (unsigned *)p; return (unsigned *)(p->pLeaves + p->nVarsMax + p->fSeq); } +static inline unsigned Cut_CutReadPhase( Cut_Cut_t * p ) { return p->uPhase; } 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_CutReadData( Cut_Cut_t * p ) { return p->pData; } + +static inline void Cut_CutWriteData( Cut_Cut_t * p, void * pData ) { p->pData = pData; } 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]; + if ( p->nVarsMax == 4 ) { p->uTruth = *puTruth; return; } + p->pLeaves[p->nVarsMax + p->fSeq] = (int)puTruth[0]; + if ( p->nVarsMax == 6 ) p->pLeaves[p->nVarsMax + p->fSeq + 1] = (int)puTruth[1]; } //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// 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 void Cut_NodeSetTriv( Cut_Man_t * p, int Node ); +extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ); 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 +extern Cut_Cut_t * Cut_NodeReadCuts( Cut_Man_t * p, int Node ); +extern void Cut_NodeWriteCuts( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); +extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node ); +extern void Cut_NodeSetComputedAsNew( Cut_Man_t * p, int Node ); +extern void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node ); +extern void Cut_CutPrint( Cut_Cut_t * pCut ); //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + 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 index 17f268c7..fe5080b4 100644 --- a/src/opt/cut/cutInt.h +++ b/src/opt/cut/cutInt.h @@ -29,7 +29,6 @@ #include "extra.h" #include "vec.h" #include "cut.h" -#include "cutList.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -42,103 +41,56 @@ 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 + Vec_Ptr_t * vCuts; // cuts by ID + Vec_Ptr_t * vCutsNew; // cuts by ID + Cut_HashTable_t * tTable; // cuts by their leaves (and root) // 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; + // precomputations + unsigned uTruthVars[6][2]; + unsigned short ** pPerms43; + unsigned ** pPerms53; + unsigned ** pPerms54; // statistics int nCutsCur; int nCutsAlloc; int nCutsDealloc; int nCutsPeak; int nCutsTriv; - int nCutsFilter; - int nCutsLimit; + int nCutsNode; 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 /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// -// 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 ); +extern Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p ); /*=== cutTable.c ==========================================================*/ extern Cut_HashTable_t * Cut_TableStart( int Size ); extern void Cut_TableStop( Cut_HashTable_t * pTable ); @@ -146,12 +98,11 @@ extern int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t 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 +extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/opt/cut/cutList.h b/src/opt/cut/cutList.h index a03ec9d5..eb008ef9 100644 --- a/src/opt/cut/cutList.h +++ b/src/opt/cut/cutList.h @@ -36,12 +36,12 @@ 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]; + Cut_Cut_t * pHead[7]; + Cut_Cut_t ** ppTail[7]; }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -50,7 +50,7 @@ struct Cut_ListStruct_t_ /**Function************************************************************* - Synopsis [Start the cut list.] + Synopsis [] Description [] @@ -62,7 +62,7 @@ struct Cut_ListStruct_t_ static inline void Cut_ListStart( Cut_List_t * p ) { int i; - for ( i = 1; i <= CUT_SIZE_MAX; i++ ) + for ( i = 1; i <= 6; i++ ) { p->pHead[i] = 0; p->ppTail[i] = &p->pHead[i]; @@ -71,7 +71,7 @@ static inline void Cut_ListStart( Cut_List_t * p ) /**Function************************************************************* - Synopsis [Adds one cut to the cut list.] + Synopsis [] Description [] @@ -82,100 +82,14 @@ static inline void Cut_ListStart( Cut_List_t * p ) ***********************************************************************/ static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut ) { - assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX ); + assert( pCut->nLeaves > 0 && pCut->nLeaves < 7 ); *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.] + Synopsis [] Description [] @@ -186,22 +100,16 @@ static inline void Cut_ListAddList( Cut_List_t * pOld, Cut_List_t * pNew ) ***********************************************************************/ 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; + for ( i = 1; i < 6; i++ ) + *p->ppTail[i] = p->pHead[i+1]; + *p->ppTail[6] = NULL; + return p->pHead[1]; } -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/opt/cut/cutMan.c b/src/opt/cut/cutMan.c index 8593ef93..4ad3a66a 100644 --- a/src/opt/cut/cutMan.c +++ b/src/opt/cut/cutMan.c @@ -24,10 +24,8 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern void Npn_StartTruth8( uint8 uTruths[][32] ); - //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -45,65 +43,47 @@ 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 ); + assert( pParams->nVarsMax >= 4 && pParams->nVarsMax <= 6 ); 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 ( p->pParams->fSeq ) + p->pParams->fHash = 1; + // space for cuts + p->vCuts = Vec_PtrAlloc( pParams->nIdsMax ); + Vec_PtrFill( p->vCuts, pParams->nIdsMax, NULL ); 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" ); - } + p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax ); + Vec_PtrFill( p->vCuts, pParams->nIdsMax, NULL ); } + // hash tables + if ( pParams->fHash ) + p->tTable = Cut_TableStart( p->pParams->nKeepMax ); // 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 ); - } + p->EntrySize = sizeof(Cut_Cut_t) + (pParams->nVarsMax + pParams->fSeq) * sizeof(int); + if ( pParams->nVarsMax == 5 ) + p->EntrySize += sizeof(unsigned); + else if ( pParams->nVarsMax == 6 ) + p->EntrySize += 2 * sizeof(unsigned); // memory for cuts p->pMmCuts = Extra_MmFixedStart( p->EntrySize ); + // precomputations +// if ( pParams->fTruth && pParams->nVarsMax == 4 ) +// p->pPerms43 = Extra_TruthPerm43(); +// else if ( pParams->fTruth ) +// { +// p->pPerms53 = Extra_TruthPerm53(); +// p->pPerms54 = Extra_TruthPerm54(); +// } + p->uTruthVars[0][1] = p->uTruthVars[0][0] = 0xAAAAAAAA; // 1010 1010 1010 1010 1010 1010 1010 1010 + p->uTruthVars[1][1] = p->uTruthVars[1][0] = 0xCCCCCCCC; // 1010 1010 1010 1010 1010 1010 1010 1010 + p->uTruthVars[2][1] = p->uTruthVars[2][0] = 0xF0F0F0F0; // 1111 0000 1111 0000 1111 0000 1111 0000 + p->uTruthVars[3][1] = p->uTruthVars[3][0] = 0xFF00FF00; // 1111 1111 0000 0000 1111 1111 0000 0000 + p->uTruthVars[4][1] = p->uTruthVars[4][0] = 0xFFFF0000; // 1111 1111 1111 1111 0000 0000 0000 0000 + p->uTruthVars[5][0] = 0x00000000; + p->uTruthVars[5][1] = 0xFFFFFFFF; p->vTemp = Vec_PtrAlloc( 100 ); return p; } @@ -123,29 +103,23 @@ 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 ) + Vec_PtrForEachEntry( p->vCuts, 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 ); + } + + if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew ); + if ( p->vCuts ) Vec_PtrFree( p->vCuts ); + if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts ); + if ( p->pPerms43 ) free( p->pPerms43 ); + if ( p->pPerms53 ) free( p->pPerms53 ); + if ( p->pPerms54 ) free( p->pPerms54 ); + if ( p->vTemp ) Vec_PtrFree( p->vTemp ); + if ( p->tTable ) Cut_TableStop( p->tTable ); + Extra_MmFixedStop( p->pMmCuts, 0 ); free( p ); } @@ -162,66 +136,21 @@ void Cut_ManStop( Cut_Man_t * p ) ***********************************************************************/ 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( "Hash ", Cut_TableReadTime(p->tTable) ); 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************************************************************* @@ -239,86 +168,6 @@ 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 index d8a9989c..ba1afce4 100644 --- a/src/opt/cut/cutMerge.c +++ b/src/opt/cut/cutMerge.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -39,7 +39,7 @@ SeeAlso [] ***********************************************************************/ -Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +Cut_Cut_t * Cut_CutMergeTwo( 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; @@ -164,7 +164,7 @@ Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut SeeAlso [] ***********************************************************************/ -Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { Cut_Cut_t * pRes; int * pLeaves; @@ -526,7 +526,7 @@ Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut return NULL; } pRes = Cut_CutAlloc( p ); - pRes->Num1 = uSign1; + pRes->uTruth = (uSign1 << 8); } for ( i = 0; i < (int)pCut0->nLeaves; i++ ) pRes->pLeaves[i] = pCut0->pLeaves[i]; @@ -645,8 +645,7 @@ Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut } assert( Count == nNodes ); pRes->nLeaves = nNodes; - pRes->Num1 = uSign1; - pRes->Num0 = uSign0; + pRes->uTruth = (uSign1 << 8) | uSign0; return pRes; } diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c index 1f93b14b..8d16ac8a 100644 --- a/src/opt/cut/cutNode.c +++ b/src/opt/cut/cutNode.c @@ -19,21 +19,42 @@ ***********************************************************************/ #include "cutInt.h" +#include "cutList.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 ); +static inline Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node ); +static inline void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut ); +static inline int Cut_CutProcessTwo( Cut_Man_t * p, int Root, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList ); + +static void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); +static void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList ); + +// 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 ) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Returns 1 if pDom is contained in pCut.] + Synopsis [Returns the pointer to the linked list of cuts.] Description [] @@ -42,24 +63,16 @@ static int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Nod SeeAlso [] ***********************************************************************/ -static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut ) +Cut_Cut_t * Cut_NodeReadCuts( Cut_Man_t * p, int Node ) { - 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; + if ( Node >= p->vCuts->nSize ) + return NULL; + return Vec_PtrEntry( p->vCuts, Node ); } /**Function************************************************************* - Synopsis [Filters cuts using dominance.] + Synopsis [Returns the pointer to the linked list of cuts.] Description [] @@ -68,293 +81,14 @@ static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut ) 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 ) +void Cut_NodeWriteCuts( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) { - 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; + Vec_PtrWriteEntry( p->vCuts, Node, pList ); } /**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.] + Synopsis [Sets the trivial cut for the node.] Description [] @@ -363,68 +97,15 @@ static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t SeeAlso [] ***********************************************************************/ -Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ) +void Cut_NodeSetTriv( Cut_Man_t * p, int Node ) { - 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; + assert( Cut_NodeReadCuts(p, Node) == NULL ); + Cut_NodeWriteCuts( p, Node, Cut_CutCreateTriv(p, Node) ); } /**Function************************************************************* - Synopsis [Returns optimum delay mapping.] + Synopsis [Deallocates the cuts at the node.] Description [] @@ -433,96 +114,21 @@ p->timeMap += clock() - clk; SeeAlso [] ***********************************************************************/ -int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) +void Cut_NodeFreeCuts( Cut_Man_t * p, int Node ) { - 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; + Cut_Cut_t * pList, * pCut, * pCut2; + pList = Cut_NodeReadCuts( p, Node ); + if ( pList == NULL ) + return; + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + Cut_NodeWriteCuts( p, Node, NULL ); } -/**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.] + Synopsis [] Description [] @@ -531,23 +137,10 @@ int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int SeeAlso [] ***********************************************************************/ -int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ) +void Cut_NodeSetComputedAsNew( 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.] @@ -559,43 +152,24 @@ int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ) 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 * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ) { - 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++; - } + Cut_List_t SuperList; + Cut_Cut_t * pList0, * pList1, * pStop0, * pStop1, * pTemp0, * pTemp1; + int i, Limit = p->pParams->nVarsMax; + int clk = clock(); + assert( p->pParams->nVarsMax <= 6 ); + // start the new list + Cut_ListStart( &SuperList ); // 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; + pList0 = Cut_NodeReadCuts( p, Node0 ); + pList1 = Cut_NodeReadCuts( p, Node1 ); + assert( pList0 && pList1 ); // 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 ) @@ -603,54 +177,101 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC Cut_ListForEachCut( pList1, pStop1 ) if ( pStop1->nLeaves == (unsigned)Limit ) break; - + // start with the elementary cut + pTemp0 = Cut_CutCreateTriv( p, Node ); + Cut_ListAdd( &SuperList, pTemp0 ); + p->nCutsNode = 1; // 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 ) + if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) ) + goto finish; + // all by large + Cut_ListForEachCut( pList0, pTemp0 ) 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 ) + if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) ) + goto finish; + // all by large + Cut_ListForEachCut( pList1, pTemp1 ) Cut_ListForEachCut( pStop0, pTemp0 ) - { - if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign ) - continue; - if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - goto Quits; - } + if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) ) + goto finish; // 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; + if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) ) + goto finish; + } +finish : + // set the list at the node + Vec_PtrFillExtra( p->vCuts, Node + 1, NULL ); + assert( Cut_NodeReadCuts(p, Node) == NULL ); + pList0 = Cut_ListFinish( &SuperList ); + Cut_NodeWriteCuts( p, Node, pList0 ); + // clear the hash table + if ( p->pParams->fHash && !p->pParams->fSeq ) + Cut_TableClear( p->tTable ); + // consider dropping the fanins cuts + if ( p->pParams->fDrop ) + { + Cut_NodeTryDroppingCuts( p, Node0 ); + Cut_NodeTryDroppingCuts( p, Node1 ); + } +p->timeMerge += clock() - clk; + // filter the cuts +clk = clock(); + if ( p->pParams->fFilter ) + Cut_CutFilter( p, pList0 ); +p->timeFilter += clock() - clk; + p->nNodes++; + return pList0; +} + +/**Function************************************************************* + + Synopsis [Processes two cuts.] + + Description [Returns 1 if the limit has been reached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CutProcessTwo( Cut_Man_t * p, int Root, 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( pCut->nLeaves > 1 ); + // add the root if sequential + if ( p->pParams->fSeq ) + pCut->pLeaves[pCut->nLeaves] = Root; + // check the lookup table + if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) ) + { + Cut_CutRecycle( p, pCut ); + return 0; + } + // compute the truth table + if ( p->pParams->fTruth ) + Cut_TruthCompute( p, pCut, pCut0, pCut1 ); + // add to the list + Cut_ListAdd( pSuperList, pCut ); + // return status (0 if okay; 1 if exceeded the limit) + return ++p->nCutsNode == p->pParams->nKeepMax; } /**Function************************************************************* @@ -666,32 +287,33 @@ Quits: ***********************************************************************/ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ) { - Cut_List_t Super, * pSuper = &Super; + Cut_List_t SuperList; Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop; int i, k, Node, Root, Limit = p->pParams->nVarsMax; int clk = clock(); + assert( p->pParams->nVarsMax <= 6 ); + // start the new list - Cut_ListStart( pSuper ); + Cut_ListStart( &SuperList ); // remember the root node to save the resulting cuts Root = Vec_IntEntry( vNodes, 0 ); - p->nNodeCuts = 1; + p->nCutsNode = 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 ); + pList = Cut_NodeReadCuts( p, Node ); + Cut_NodeWriteCuts( 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; + Cut_ListAdd( &SuperList, pList ), pTop = pList; else Cut_CutRecycle( p, pList ); // save all the cuts that are smaller than the limit @@ -702,19 +324,20 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ) Vec_PtrPush( p->vTemp, pCut ); break; } - // check containment - if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) + // check hash tables + if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) ) + { + Cut_CutRecycle( p, 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 ) + Cut_ListAdd( &SuperList, pCut ); + if ( ++p->nCutsNode == p->pParams->nKeepMax ) { // recycle the rest of the cuts of this node - Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) + Cut_ListForEachCutSafe( pCut->pNext, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle all cuts of other nodes Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) @@ -726,25 +349,25 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ) 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 ) ) + if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) ) + { + Cut_CutRecycle( p, 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 ) + Cut_ListAdd( &SuperList, pCut ); + if ( ++p->nCutsNode == p->pParams->nKeepMax ) { // recycle the rest of the cuts - Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) + Cut_ListForEachCutSafe( pCut->pNext, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle the saved cuts of other nodes Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 ) @@ -756,22 +379,25 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ) } finish : // set the cuts at the node - assert( Cut_NodeReadCutsNew(p, Root) == NULL ); - pList = Cut_ListFinish( pSuper ); - Cut_NodeWriteCutsNew( p, Root, pList ); + assert( Cut_NodeReadCuts(p, Root) == NULL ); + pList = Cut_ListFinish( &SuperList ); + Cut_NodeWriteCuts( p, Root, pList ); + // clear the hash table + if ( p->pParams->fHash && !p->pParams->fSeq ) + Cut_TableClear( p->tTable ); p->timeUnion += clock() - clk; // filter the cuts -//clk = clock(); -// if ( p->pParams->fFilter ) -// Cut_CutFilter( p, pList ); -//p->timeFilter += clock() - clk; +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.] + Synopsis [Start the cut computation.] Description [] @@ -780,182 +406,157 @@ p->timeUnion += clock() - clk; SeeAlso [] ***********************************************************************/ -Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ) +Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p ) { - 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(); + 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->fSeq = p->pParams->fSeq; + pCut->fSimul = p->fSimul; + // statistics + p->nCutsAlloc++; + p->nCutsCur++; + if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc ) + p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc; + return pCut; +} - // start the new list - Cut_ListStart( pSuper ); +/**Function************************************************************* - // remember the root node to save the resulting cuts - Root = Vec_IntEntry( vNodes, 0 ); - p->nNodeCuts = 1; + Synopsis [Start the cut computation.] - // store the original lists for comparison - p->pCompareOld = Cut_NodeReadCutsOld( p, Root ); - p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL; + Description [] + + SideEffects [] - // get the topmost cut - pTop = NULL; - if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL ) - pTop = Cut_NodeReadCutsNew( p, Root ); - assert( pTop != NULL ); + SeeAlso [] - // 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; +***********************************************************************/ +Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node ) +{ + Cut_Cut_t * pCut; + pCut = Cut_CutAlloc( p ); + pCut->nLeaves = 1; + pCut->pLeaves[0] = Node; + if ( p->pParams->fTruth ) + Cut_CutWriteTruth( pCut, p->uTruthVars[0] ); + p->nCutsTriv++; + return pCut; +} - // 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; +/**Function************************************************************* - // 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; - } - } + Synopsis [Start the cut computation.] - // 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; - } - } + Description [] + + SideEffects [] - // 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 ); + SeeAlso [] - // 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 ); - } +***********************************************************************/ +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 ); +} -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 [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 [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CutPrint( Cut_Cut_t * pCut ) +{ + int i; + assert( pCut->nLeaves > 0 ); + printf( "%d : {", pCut->nLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + printf( " %d", pCut->pLeaves[i] ); + printf( " }" ); +} + +/**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 + ); } /**Function************************************************************* - Synopsis [Verifies that the list contains only non-dominated cuts.] + Synopsis [Filter the cuts using dominance.] Description [] @@ -964,27 +565,62 @@ p->timeUnion += clock() - clk; SeeAlso [] ***********************************************************************/ -int Cut_CutListVerify( Cut_Cut_t * pList ) +void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList ) { - Cut_Cut_t * pCut, * pDom; - Cut_ListForEachCut( pList, pCut ) + Cut_Cut_t * pListR, ** ppListR = &pListR; + Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev; + int i, k; + // save the first cut + *ppListR = pList, ppListR = &pList->pNext; + // try to filter out other cuts + pPrev = pList; + Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 ) { - Cut_ListForEachCutStop( pList, pDom, pCut ) + assert( pCut->nLeaves > 1 ); + // go through all the previous cuts up to pCut + Cut_ListForEachCutStop( pList->pNext, pDom, pCut ) { - if ( Cut_CutCheckDominance( pDom, pCut ) ) + if ( pDom->nLeaves >= pCut->nLeaves ) + continue; + // check if every node in pDom is contained in pCut + for ( i = 0; i < (int)pDom->nLeaves; i++ ) { - int x = 0; - printf( "******************* These are contained cuts:\n" ); - Cut_CutPrint( pDom, 1 ); - Cut_CutPrint( pDom, 1 ); - - return 0; + 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 + break; } + if ( i == (int)pDom->nLeaves ) // every node in pDom is contained in pCut + break; + } + if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut + { + // make sure cuts are connected after removing + pPrev->pNext = pCut->pNext; +/* + // report + printf( "Recycling cut: " ); + Cut_CutPrint( pCut ); + printf( "\n" ); + printf( "As contained in: " ); + Cut_CutPrint( pDom ); + printf( "\n" ); +*/ + // recycle the cut + Cut_CutRecycle( p, pCut ); + } + else // pDom is NOT contained in pCut - save pCut + { + *ppListR = pCut, ppListR = &pCut->pNext; + pPrev = pCut; } } - return 1; + *ppListR = NULL; } + + //////////////////////////////////////////////////////////////////////// /// 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 index d36f94f7..869bd7b3 100644 --- a/src/opt/cut/cutSeq.c +++ b/src/opt/cut/cutSeq.c @@ -25,12 +25,12 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Shifts all cut leaves of the node by the given number of latches.] + Synopsis [] Description [] @@ -39,186 +39,6 @@ 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/cutTable.c b/src/opt/cut/cutTable.c new file mode 100644 index 00000000..5dfaca7b --- /dev/null +++ b/src/opt/cut/cutTable.c @@ -0,0 +1,253 @@ +/**CFile**************************************************************** + + FileName [cutTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Hashing cuts to prevent duplication.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Cut_HashTableStruct_t_ +{ + int nBins; + Cut_Cut_t ** pBins; + int nEntries; + int * pPlaces; + int nPlaces; + int timeLookup; +}; + +// iterator through all the cuts of the list +#define Cut_TableListForEachCut( pList, pCut ) \ + for ( pCut = pList; \ + pCut; \ + pCut = pCut->pData ) +#define Cut_TableListForEachCutSafe( pList, pCut, pCut2 ) \ + for ( pCut = pList, \ + pCut2 = pCut? pCut->pData: NULL; \ + pCut; \ + pCut = pCut2, \ + pCut2 = pCut? pCut->pData: NULL ) + +// primes used to compute the hash key +static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; + +// hashing function +static inline unsigned Cut_HashKey( Cut_Cut_t * pCut ) +{ + unsigned i, uRes = pCut->nLeaves * s_HashPrimes[9]; + for ( i = 0; i < pCut->nLeaves + pCut->fSeq; i++ ) + uRes += s_HashPrimes[i] * pCut->pLeaves[i]; + return uRes; +} + +// hashing function +static inline int Cut_CompareTwo( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ) +{ + unsigned i; + if ( pCut1->nLeaves != pCut2->nLeaves ) + return 1; + for ( i = 0; i < pCut1->nLeaves; i++ ) + if ( pCut1->pLeaves[i] != pCut2->pLeaves[i] ) + return 1; + return 0; +} + +static void Cut_TableResize( Cut_HashTable_t * pTable ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_HashTable_t * Cut_TableStart( int Size ) +{ + Cut_HashTable_t * pTable; + pTable = ALLOC( Cut_HashTable_t, 1 ); + memset( pTable, 0, sizeof(Cut_HashTable_t) ); + // allocate the table + pTable->nBins = Cudd_PrimeCopy( Size ); + pTable->pBins = ALLOC( Cut_Cut_t *, pTable->nBins ); + memset( pTable->pBins, 0, sizeof(Cut_Cut_t *) * pTable->nBins ); + pTable->pPlaces = ALLOC( int, pTable->nBins ); + return pTable; +} + +/**Function************************************************************* + + Synopsis [Stops the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TableStop( Cut_HashTable_t * pTable ) +{ + FREE( pTable->pPlaces ); + free( pTable->pBins ); + free( pTable ); +} + +/**Function************************************************************* + + Synopsis [Check the existence of a cut in the lookup table] + + Description [Returns 1 if the entry is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t * pCut, int fStore ) +{ + Cut_Cut_t * pEnt; + unsigned Key; + int clk = clock(); + + Key = Cut_HashKey(pCut) % pTable->nBins; + Cut_TableListForEachCut( pTable->pBins[Key], pEnt ) + { + if ( !Cut_CompareTwo( pEnt, pCut ) ) + { +pTable->timeLookup += clock() - clk; + return 1; + } + } + if ( pTable->nEntries > 2 * pTable->nBins ) + { + Cut_TableResize( pTable ); + Key = Cut_HashKey(pCut) % pTable->nBins; + } + // remember the place + if ( fStore && pTable->pBins[Key] == NULL ) + pTable->pPlaces[ pTable->nPlaces++ ] = Key; + // add the cut to the table + pCut->pData = pTable->pBins[Key]; + pTable->pBins[Key] = pCut; + pTable->nEntries++; +pTable->timeLookup += clock() - clk; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Stops the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TableClear( Cut_HashTable_t * pTable ) +{ + int i; + assert( pTable->nPlaces <= pTable->nBins ); + for ( i = 0; i < pTable->nPlaces; i++ ) + { + assert( pTable->pBins[ pTable->pPlaces[i] ] ); + pTable->pBins[ pTable->pPlaces[i] ] = NULL; + } + pTable->nPlaces = 0; + pTable->nEntries = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TableResize( Cut_HashTable_t * pTable ) +{ + Cut_Cut_t ** pBinsNew; + Cut_Cut_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Cudd_PrimeCopy( 3 * pTable->nBins ); + // allocate a new array + pBinsNew = ALLOC( Cut_Cut_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Cut_Cut_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pTable->nBins; i++ ) + Cut_TableListForEachCutSafe( pTable->pBins[i], pEnt, pEnt2 ) + { + Key = Cut_HashKey(pEnt) % nBinsNew; + pEnt->pData = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pTable->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( pTable->pBins ); + pTable->pBins = pBinsNew; + pTable->nBins = nBinsNew; +} + +/**Function************************************************************* + + Synopsis [Stops the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_TableReadTime( Cut_HashTable_t * pTable ) +{ + if ( pTable == NULL ) + return 0; + return pTable->timeLookup; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/opt/cut/cutTruth.c b/src/opt/cut/cutTruth.c index c3514ad7..efacd456 100644 --- a/src/opt/cut/cutTruth.c +++ b/src/opt/cut/cutTruth.c @@ -20,27 +20,21 @@ #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; +static void Cut_TruthCompute4( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); +static void Cut_TruthCompute5( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); +static void Cut_TruthCompute6( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + Synopsis [Performs truth table computation.] Description [] @@ -70,42 +64,23 @@ static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) Synopsis [Performs truth table computation.] - Description [This procedure cannot be used while recording oracle - because it will overwrite Num0 and Num1.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -void Cut_TruthNCanonicize( Cut_Cut_t * pCut ) +void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { - 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]; +int clk = clock(); + if ( pCut->nVarsMax == 4 ) + Cut_TruthCompute4( p, pCut, pCut0, pCut1 ); + else if ( pCut->nVarsMax == 5 ) + Cut_TruthCompute5( p, pCut, pCut0, pCut1 ); + else // if ( pCut->nVarsMax == 6 ) + Cut_TruthCompute6( p, pCut, pCut0, pCut1 ); +p->timeTruth += clock() - clk; } /**Function************************************************************* @@ -119,44 +94,28 @@ void Cut_TruthNCanonicize( Cut_Cut_t * pCut ) SeeAlso [] ***********************************************************************/ -void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) +void Cut_TruthCompute4( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { - static unsigned uTruth0[8], uTruth1[8]; - int nTruthWords = Cut_TruthWords( pCut->nVarsMax ); - unsigned * pTruthRes; - int i, uPhase; + unsigned * puTruthCut0, * puTruthCut1; + unsigned uTruth0, uTruth1, 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]; - } + puTruthCut0 = Cut_CutReadTruth(pCut0); + puTruthCut1 = Cut_CutReadTruth(pCut1); - // 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]; - } + uPhase = Cut_TruthPhase( pCut, pCut0 ); + uTruth0 = Extra_TruthPerm4One( *puTruthCut0, uPhase ); + uTruth0 = p->fCompl0? ~uTruth0: uTruth0; - // write the resulting table - pTruthRes = Cut_CutReadTruth(pCut); + uPhase = Cut_TruthPhase( pCut, pCut1 ); + uTruth1 = Extra_TruthPerm4One( *puTruthCut1, uPhase ); + uTruth1 = p->fCompl1? ~uTruth1: uTruth1; + uTruth1 = uTruth0 & uTruth1; 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]; - } + uTruth1 = ~uTruth1; + if ( pCut->nVarsMax == 4 ) + uTruth1 &= 0xFFFF; + Cut_CutWriteTruth( pCut, &uTruth1 ); } /**Function************************************************************* @@ -170,55 +129,192 @@ void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 SeeAlso [] ***********************************************************************/ -void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) +void Cut_TruthCompute5( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { - // 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 + unsigned * puTruthCut0, * puTruthCut1; + unsigned uTruth0, uTruth1, uPhase; + + puTruthCut0 = Cut_CutReadTruth(pCut0); + puTruthCut1 = Cut_CutReadTruth(pCut1); + + uPhase = Cut_TruthPhase( pCut, pCut0 ); + uTruth0 = Extra_TruthPerm5One( *puTruthCut0, uPhase ); + uTruth0 = p->fCompl0? ~uTruth0: uTruth0; + + uPhase = Cut_TruthPhase( pCut, pCut1 ); + uTruth1 = Extra_TruthPerm5One( *puTruthCut1, uPhase ); + uTruth1 = p->fCompl1? ~uTruth1: uTruth1; + + uTruth1 = uTruth0 & uTruth1; 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 ); + uTruth1 = ~uTruth1; + Cut_CutWriteTruth( pCut, &uTruth1 ); +} + +/**Function************************************************************* -// Ivy_TruthTestOne( *Cut_CutReadTruth(pCut) ); + Synopsis [Performs truth table computation.] - // quit if no fancy computation is needed - if ( !p->pParams->fFancy ) - return; + Description [] + + SideEffects [] - if ( pCut->nLeaves != 7 ) - return; + SeeAlso [] - // count the total number of truth tables computed - nTotal++; +***********************************************************************/ +void Cut_TruthCompute6( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + unsigned * puTruthCut0, * puTruthCut1; + unsigned uTruth0[2], uTruth1[2], uPhase; - // 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++; + puTruthCut0 = Cut_CutReadTruth(pCut0); + puTruthCut1 = Cut_CutReadTruth(pCut1); + + uPhase = Cut_TruthPhase( pCut, pCut0 ); + Extra_TruthPerm6One( puTruthCut0, uPhase, uTruth0 ); + uTruth0[0] = p->fCompl0? ~uTruth0[0]: uTruth0[0]; + uTruth0[1] = p->fCompl0? ~uTruth0[1]: uTruth0[1]; - // 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 ); + uPhase = Cut_TruthPhase( pCut, pCut1 ); + Extra_TruthPerm6One( puTruthCut1, uPhase, uTruth1 ); + uTruth1[0] = p->fCompl1? ~uTruth1[0]: uTruth1[0]; + uTruth1[1] = p->fCompl1? ~uTruth1[1]: uTruth1[1]; + + uTruth1[0] = uTruth0[0] & uTruth1[0]; + uTruth1[1] = uTruth0[1] & uTruth1[1]; + if ( pCut->fCompl ) + { + uTruth1[0] = ~uTruth0[0]; + uTruth1[1] = ~uTruth0[1]; + } + Cut_CutWriteTruth( pCut, uTruth1 ); } + + + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TruthComputeOld( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + unsigned uTruth0, uTruth1, uPhase; + int clk = clock(); + + assert( pCut->nVarsMax < 6 ); + + // assign the truth table + if ( pCut0->nLeaves == pCut->nLeaves ) + uTruth0 = *Cut_CutReadTruth(pCut0); + else + { + assert( pCut0->nLeaves < pCut->nLeaves ); + uPhase = Cut_TruthPhase( pCut, pCut0 ); + if ( pCut->nVarsMax == 4 ) + { + assert( pCut0->nLeaves < 4 ); + assert( uPhase < 16 ); + uTruth0 = p->pPerms43[pCut0->uTruth & 0xFF][uPhase]; + } + else + { + assert( pCut->nVarsMax == 5 ); + assert( pCut0->nLeaves < 5 ); + assert( uPhase < 32 ); + if ( pCut0->nLeaves == 4 ) + { +// Count4++; +/* + if ( uPhase == 31-16 ) // 01111 + uTruth0 = pCut0->uTruth; + else if ( uPhase == 31-8 ) // 10111 + uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][0]; + else if ( uPhase == 31-4 ) // 11011 + uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][1]; + else if ( uPhase == 31-2 ) // 11101 + uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][2]; + else if ( uPhase == 31-1 ) // 11110 + uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][3]; + else + assert( 0 ); +*/ + uTruth0 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut0), uPhase ); + } + else + { +// Count5++; +// uTruth0 = p->pPerms53[pCut0->uTruth & 0xFF][uPhase]; + uTruth0 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut0), uPhase ); + } + } + } + uTruth0 = p->fCompl0? ~uTruth0: uTruth0; + + // assign the truth table + if ( pCut1->nLeaves == pCut->nLeaves ) + uTruth0 = *Cut_CutReadTruth(pCut1); + else + { + assert( pCut1->nLeaves < pCut->nLeaves ); + uPhase = Cut_TruthPhase( pCut, pCut1 ); + if ( pCut->nVarsMax == 4 ) + { + assert( pCut1->nLeaves < 4 ); + assert( uPhase < 16 ); + uTruth1 = p->pPerms43[pCut1->uTruth & 0xFF][uPhase]; + } + else + { + assert( pCut->nVarsMax == 5 ); + assert( pCut1->nLeaves < 5 ); + assert( uPhase < 32 ); + if ( pCut1->nLeaves == 4 ) + { +// Count4++; +/* + if ( uPhase == 31-16 ) // 01111 + uTruth1 = pCut1->uTruth; + else if ( uPhase == 31-8 ) // 10111 + uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][0]; + else if ( uPhase == 31-4 ) // 11011 + uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][1]; + else if ( uPhase == 31-2 ) // 11101 + uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][2]; + else if ( uPhase == 31-1 ) // 11110 + uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][3]; + else + assert( 0 ); +*/ + uTruth1 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut1), uPhase ); + } + else + { +// Count5++; +// uTruth1 = p->pPerms53[pCut1->uTruth & 0xFF][uPhase]; + uTruth1 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut1), uPhase ); + } + } + } + uTruth1 = p->fCompl1? ~uTruth1: uTruth1; + uTruth1 = uTruth0 & uTruth1; + if ( pCut->fCompl ) + uTruth1 = ~uTruth1; + if ( pCut->nVarsMax == 4 ) + uTruth1 &= 0xFFFF; + Cut_CutWriteTruth( pCut, &uTruth1 ); +p->timeTruth += clock() - clk; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/cut/module.make b/src/opt/cut/module.make index 132e730b..1175b3f2 100644 --- a/src/opt/cut/module.make +++ b/src/opt/cut/module.make @@ -1,9 +1,6 @@ -SRC += src/opt/cut/cutApi.c \ - src/opt/cut/cutCut.c \ - src/opt/cut/cutMan.c \ +SRC += 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/cutTable.c \ src/opt/cut/cutTruth.c diff --git a/src/opt/dec/dec.h b/src/opt/dec/dec.h index d0d9981d..6ecc9678 100644 --- a/src/opt/dec/dec.h +++ b/src/opt/dec/dec.h @@ -21,10 +21,6 @@ #ifndef __DEC_H__ #define __DEC_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -51,15 +47,11 @@ struct Dec_Node_t_ 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 + unsigned Level : 16; // 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; @@ -103,6 +95,9 @@ struct Dec_Man_t_ //////////////////////////////////////////////////////////////////////// /*=== decAbc.c ========================================================*/ +extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Aig_t * pMan, 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, int nGain ); /*=== decFactor.c ========================================================*/ extern Dec_Graph_t * Dec_Factor( char * pSop ); /*=== decMan.c ========================================================*/ @@ -111,10 +106,11 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -312,7 +308,7 @@ static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) SeeAlso [] ***********************************************************************/ -static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph ) +static inline bool Dec_GraphIsConst( Dec_Graph_t * pGraph ) { return pGraph->fConst; } @@ -328,7 +324,7 @@ static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph ) SeeAlso [] ***********************************************************************/ -static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph ) +static inline bool Dec_GraphIsConst0( Dec_Graph_t * pGraph ) { return pGraph->fConst && pGraph->eRoot.fCompl; } @@ -344,7 +340,7 @@ static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph ) SeeAlso [] ***********************************************************************/ -static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph ) +static inline bool Dec_GraphIsConst1( Dec_Graph_t * pGraph ) { return pGraph->fConst && !pGraph->eRoot.fCompl; } @@ -360,7 +356,7 @@ static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph ) SeeAlso [] ***********************************************************************/ -static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph ) +static inline bool Dec_GraphIsComplement( Dec_Graph_t * pGraph ) { return pGraph->eRoot.fCompl; } @@ -473,7 +469,7 @@ static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) SeeAlso [] ***********************************************************************/ -static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph ) +static inline bool Dec_GraphIsVar( Dec_Graph_t * pGraph ) { return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; } @@ -489,7 +485,7 @@ static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph ) SeeAlso [] ***********************************************************************/ -static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) +static inline bool Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) { return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; } @@ -631,84 +627,24 @@ static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eE 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 +static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) +{ + Dec_Edge_t eNode0, eNode1; + // derive the first AND + eEdge0.fCompl = !eEdge0.fCompl; + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + eEdge0.fCompl = !eEdge0.fCompl; + // derive the second AND + eEdge1.fCompl = !eEdge1.fCompl; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + eEdge1.fCompl = !eEdge1.fCompl; + // derive the final OR + return Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); } -#endif - -#endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/opt/dec/decAbc.c b/src/opt/dec/decAbc.c index 6adb0f98..9931b136 100644 --- a/src/opt/dec/decAbc.c +++ b/src/opt/dec/decAbc.c @@ -18,14 +18,13 @@ #include "abc.h" #include "dec.h" -#include "ivy.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -40,14 +39,14 @@ SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) +Abc_Obj_t * Dec_GraphToNetwork( Abc_Aig_t * pMan, 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) ); + return Abc_ObjNotCond( Abc_AigConst1(pMan), Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); @@ -56,45 +55,7 @@ Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) { 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; + pNode->pFunc = Abc_AigAnd( pMan, pAnd0, pAnd1 ); } // complement the result if necessary return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); @@ -158,14 +119,14 @@ int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMa LevelNew = 1 + ABC_MAX( pNode0->Level, pNode1->Level ); if ( pAnd ) { - if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pRoot->pNtk) ) + if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pMan) ) 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 ); + assert( LevelNew == LevelOld ); } if ( LevelNew > LevelMax ) return -1; @@ -187,118 +148,21 @@ int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMa SeeAlso [] ***********************************************************************/ -void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ) +void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ) { - extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ); 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 ); + pRootNew = Dec_GraphToNetwork( pNtk->pManFunc, pGraph ); // remove the old nodes - Abc_AigReplace( pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel ); + Abc_AigReplace( pNtk->pManFunc, pRoot, pRootNew ); // 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 index 768dcd9b..f6654476 100644 --- a/src/opt/dec/decFactor.c +++ b/src/opt/dec/decFactor.c @@ -34,7 +34,7 @@ static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ); static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -183,7 +183,7 @@ Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) ***********************************************************************/ Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) { - Dec_Man_t * pManDec = Abc_FrameReadManDec(); + Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame()); Vec_Int_t * vEdgeLits = pManDec->vLits; Mvc_Cover_t * pDiv, * pQuo, * pRem; Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; @@ -228,7 +228,7 @@ Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cov ***********************************************************************/ Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) { - Dec_Man_t * pManDec = Abc_FrameReadManDec(); + Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame()); Vec_Int_t * vEdgeCubes = pManDec->vCubes; Vec_Int_t * vEdgeLits = pManDec->vLits; Mvc_Manager_t * pMem = pManDec->pMvcMem; @@ -258,15 +258,16 @@ Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) ***********************************************************************/ 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; +// 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) ); +// eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST +// Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) ); + Vec_IntPush( vEdgeLits, iBit ); } // balance the factored forms return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 ); @@ -322,7 +323,7 @@ Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes ***********************************************************************/ Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ) { - Dec_Man_t * pManDec = Abc_FrameReadManDec(); + Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame()); Mvc_Manager_t * pMem = pManDec->pMvcMem; Mvc_Cover_t * pMvc; Mvc_Cube_t * pMvcCube; @@ -364,8 +365,7 @@ Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ) ***********************************************************************/ int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ) { - extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ); - DdManager * dd = Abc_FrameReadManDd(); + DdManager * dd = Abc_FrameReadManDd( Abc_FrameGetGlobalFrame() ); DdNode * bFunc1, * bFunc2; int RetValue; bFunc1 = Abc_ConvertSopToBdd( dd, pSop ); Cudd_Ref( bFunc1 ); diff --git a/src/opt/dec/decMan.c b/src/opt/dec/decMan.c index 65857461..1d44d5cb 100644 --- a/src/opt/dec/decMan.c +++ b/src/opt/dec/decMan.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/dec/decPrint.c b/src/opt/dec/decPrint.c index 2d8f09b3..6fb20327 100644 --- a/src/opt/dec/decPrint.c +++ b/src/opt/dec/decPrint.c @@ -29,7 +29,7 @@ static void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax static int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -101,7 +101,7 @@ void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char SeeAlso [] ***********************************************************************/ -void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) +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; pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); @@ -154,69 +154,6 @@ void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode 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 [] diff --git a/src/opt/dec/decUtil.c b/src/opt/dec/decUtil.c index 463bc7e2..02c3346e 100644 --- a/src/opt/dec/decUtil.c +++ b/src/opt/dec/decUtil.c @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/fret/fretFlow.c b/src/opt/fret/fretFlow.c deleted file mode 100644 index a9cef327..00000000 --- a/src/opt/fret/fretFlow.c +++ /dev/null @@ -1,696 +0,0 @@ -/**CFile**************************************************************** - - FileName [fretFlow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Flow-based retiming package.] - - Synopsis [Max-flow computation.] - - Author [Aaron Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2008.] - - Revision [$Id: fretFlow.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "vec.h" -#include "fretime.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void dfsfast_e_retreat( Abc_Obj_t *pObj ); -static void dfsfast_r_retreat( Abc_Obj_t *pObj ); - -#define FDIST(xn, xe, yn, ye) (FDATA(xn)->xe##_dist == (FDATA(yn)->ye##_dist + 1)) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Fast DFS.] - - Description [Uses sink-distance-histogram heuristic. May not find all - flow paths: this occurs in a small number of cases where - the flow predecessor points to a non-adjacent node and - the distance ordering is perturbed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -void dfsfast_preorder( Abc_Ntk_t *pNtk ) { - Abc_Obj_t *pObj, *pNext; - Vec_Ptr_t *vTimeIn, *qn = Vec_PtrAlloc(Abc_NtkObjNum(pNtk)); - Vec_Int_t *qe = Vec_IntAlloc(Abc_NtkObjNum(pNtk)); - int i, j, d = 0, end; - int qpos = 0; - - // create reverse timing edges for backward traversal -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay) { - Abc_NtkForEachObj( pNtk, pObj, i ) { - Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, j ) { - vTimeIn = FDATA(pNext)->vNodes; - if (!vTimeIn) { - vTimeIn = FDATA(pNext)->vNodes = Vec_PtrAlloc(2); - } - Vec_PtrPush(vTimeIn, pObj); - } - } - } -#endif - - // clear histogram - memset(Vec_IntArray(pManMR->vSinkDistHist), 0, sizeof(int)*Vec_IntSize(pManMR->vSinkDistHist)); - - // seed queue : latches, PIOs, and blocks - Abc_NtkForEachObj( pNtk, pObj, i ) - if (Abc_ObjIsPo(pObj) || - Abc_ObjIsLatch(pObj) || - (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) { - Vec_PtrPush(qn, pObj); - Vec_IntPush(qe, 'r'); - FDATA(pObj)->r_dist = 1; - } else if (Abc_ObjIsPi(pObj) || - (!pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) { - Vec_PtrPush(qn, pObj); - Vec_IntPush(qe, 'e'); - FDATA(pObj)->e_dist = 1; - } - - // until queue is empty... - while(qpos < Vec_PtrSize(qn)) { - pObj = (Abc_Obj_t *)Vec_PtrEntry(qn, qpos); - assert(pObj); - end = Vec_IntEntry(qe, qpos); - qpos++; - - if (end == 'r') { - d = FDATA(pObj)->r_dist; - - // 1. structural edges - if (pManMR->fIsForward) { - Abc_ObjForEachFanin( pObj, pNext, i ) - if (!FDATA(pNext)->e_dist) { - FDATA(pNext)->e_dist = d+1; - Vec_PtrPush(qn, pNext); - Vec_IntPush(qe, 'e'); - } - } else - Abc_ObjForEachFanout( pObj, pNext, i ) - if (!FDATA(pNext)->e_dist) { - FDATA(pNext)->e_dist = d+1; - Vec_PtrPush(qn, pNext); - Vec_IntPush(qe, 'e'); - } - - if (d == 1) continue; - - // 2. reverse edges (forward retiming only) - if (pManMR->fIsForward) { - Abc_ObjForEachFanout( pObj, pNext, i ) - if (!FDATA(pNext)->r_dist && !Abc_ObjIsLatch(pNext)) { - FDATA(pNext)->r_dist = d+1; - Vec_PtrPush(qn, pNext); - Vec_IntPush(qe, 'r'); - } - - // 3. timimg edges (forward retiming only) -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay && FDATA(pObj)->vNodes) - Vec_PtrForEachEntry( FDATA(pObj)->vNodes, pNext, i ) { - if (!FDATA(pNext)->r_dist) { - FDATA(pNext)->r_dist = d+1; - Vec_PtrPush(qn, pNext); - Vec_IntPush(qe, 'r'); - } - } -#endif - } - - } else { // if 'e' - if (Abc_ObjIsLatch(pObj)) continue; - - d = FDATA(pObj)->e_dist; - - // 1. through node - if (!FDATA(pObj)->r_dist) { - FDATA(pObj)->r_dist = d+1; - Vec_PtrPush(qn, pObj); - Vec_IntPush(qe, 'r'); - } - - // 2. reverse edges (backward retiming only) - if (!pManMR->fIsForward) { - Abc_ObjForEachFanin( pObj, pNext, i ) - if (!FDATA(pNext)->e_dist && !Abc_ObjIsLatch(pNext)) { - FDATA(pNext)->e_dist = d+1; - Vec_PtrPush(qn, pNext); - Vec_IntPush(qe, 'e'); - } - - // 3. timimg edges (backward retiming only) -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay && FDATA(pObj)->vNodes) - Vec_PtrForEachEntry( FDATA(pObj)->vNodes, pNext, i ) { - if (!FDATA(pNext)->e_dist) { - FDATA(pNext)->e_dist = d+1; - Vec_PtrPush(qn, pNext); - Vec_IntPush(qe, 'e'); - } - } -#endif - } - } - } - - // free time edges -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay) { - Abc_NtkForEachObj( pNtk, pObj, i ) { - vTimeIn = FDATA(pObj)->vNodes; - if (vTimeIn) { - Vec_PtrFree(vTimeIn); - FDATA(pObj)->vNodes = 0; - } - } - } -#endif - - Abc_NtkForEachObj( pNtk, pObj, i ) { - Vec_IntAddToEntry(pManMR->vSinkDistHist, FDATA(pObj)->r_dist, 1); - Vec_IntAddToEntry(pManMR->vSinkDistHist, FDATA(pObj)->e_dist, 1); - -#ifdef DEBUG_PREORDER - printf("node %d\t: r=%d\te=%d\n", Abc_ObjId(pObj), FDATA(pObj)->r_dist, FDATA(pObj)->e_dist); -#endif - } - - // printf("\t\tpre-ordered (max depth=%d)\n", d+1); - - // deallocate - Vec_PtrFree( qn ); - Vec_IntFree( qe ); -} - -int dfsfast_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) { - int i; - Abc_Obj_t *pNext; - - if (pManMR->fSinkDistTerminate) return 0; - - // have we reached the sink? - if(FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask || - Abc_ObjIsPi(pObj)) { - assert(pPred); - assert(!pManMR->fIsForward); - return 1; - } - - FSET(pObj, VISITED_E); - -#ifdef DEBUG_VISITED - printf("(%de=%d) ", Abc_ObjId(pObj), FDATA(pObj)->e_dist); -#endif - - // 1. structural edges - if (pManMR->fIsForward) - Abc_ObjForEachFanout( pObj, pNext, i ) { - if (!FTEST(pNext, VISITED_R) && - FDIST(pObj, e, pNext, r) && - dfsfast_r(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("o"); -#endif - goto found; - } - } - else - Abc_ObjForEachFanin( pObj, pNext, i ) { - if (!FTEST(pNext, VISITED_R) && - FDIST(pObj, e, pNext, r) && - dfsfast_r(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("o"); -#endif - goto found; - } - } - - if (Abc_ObjIsLatch(pObj)) - goto not_found; - - // 2. reverse edges (backward retiming only) - if (!pManMR->fIsForward) { - Abc_ObjForEachFanout( pObj, pNext, i ) { - if (!FTEST(pNext, VISITED_E) && - FDIST(pObj, e, pNext, e) && - dfsfast_e(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("i"); -#endif - goto found; - } - } - - // 3. timing edges (backward retiming only) -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay) - Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) { - if (!FTEST(pNext, VISITED_E) && - FDIST(pObj, e, pNext, e) && - dfsfast_e(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("o"); -#endif - goto found; - } - } -#endif - } - - // unwind - if (FTEST(pObj, FLOW) && - !FTEST(pObj, VISITED_R) && - FDIST(pObj, e, pObj, r) && - dfsfast_r(pObj, FGETPRED(pObj))) { - - FUNSET(pObj, FLOW); - FSETPRED(pObj, NULL); -#ifdef DEBUG_PRINT_FLOWS - printf("u"); -#endif - goto found; - } - - not_found: - FUNSET(pObj, VISITED_E); - dfsfast_e_retreat(pObj); - return 0; - - found: -#ifdef DEBUG_PRINT_FLOWS - printf("%d ", Abc_ObjId(pObj)); -#endif - FUNSET(pObj, VISITED_E); - return 1; -} - -int dfsfast_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) { - int i; - Abc_Obj_t *pNext, *pOldPred; - - if (pManMR->fSinkDistTerminate) return 0; - -#ifdef DEBUG_VISITED - printf("(%dr=%d) ", Abc_ObjId(pObj), FDATA(pObj)->r_dist); -#endif - - // have we reached the sink? - if (Abc_ObjIsLatch(pObj) || - (pManMR->fIsForward && Abc_ObjIsPo(pObj)) || - (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) { - assert(pPred); - return 1; - } - - FSET(pObj, VISITED_R); - - if (FTEST(pObj, FLOW)) { - - pOldPred = FGETPRED(pObj); - if (pOldPred && - !FTEST(pOldPred, VISITED_E) && - FDIST(pObj, r, pOldPred, e) && - dfsfast_e(pOldPred, pOldPred)) { - - FSETPRED(pObj, pPred); - -#ifdef DEBUG_PRINT_FLOWS - printf("fr"); -#endif - goto found; - } - - } else { - - if (!FTEST(pObj, VISITED_E) && - FDIST(pObj, r, pObj, e) && - dfsfast_e(pObj, pObj)) { - - FSET(pObj, FLOW); - FSETPRED(pObj, pPred); - -#ifdef DEBUG_PRINT_FLOWS - printf("f"); -#endif - goto found; - } - } - - // 2. reverse edges (forward retiming only) - if (pManMR->fIsForward) { - Abc_ObjForEachFanin( pObj, pNext, i ) { - if (!FTEST(pNext, VISITED_R) && - FDIST(pObj, r, pNext, r) && - !Abc_ObjIsLatch(pNext) && - dfsfast_r(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("i"); -#endif - goto found; - } - } - - // 3. timing edges (forward retiming only) -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay) - Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) { - if (!FTEST(pNext, VISITED_R) && - FDIST(pObj, r, pNext, r) && - dfsfast_r(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("o"); -#endif - goto found; - } - } -#endif - } - - FUNSET(pObj, VISITED_R); - dfsfast_r_retreat(pObj); - return 0; - - found: -#ifdef DEBUG_PRINT_FLOWS - printf("%d ", Abc_ObjId(pObj)); -#endif - FUNSET(pObj, VISITED_R); - return 1; -} - -void -dfsfast_e_retreat(Abc_Obj_t *pObj) { - Abc_Obj_t *pNext; - int i, *h; - int old_dist = FDATA(pObj)->e_dist; - int adj_dist, min_dist = MAX_DIST; - - // 1. structural edges - if (pManMR->fIsForward) - Abc_ObjForEachFanout( pObj, pNext, i ) { - adj_dist = FDATA(pNext)->r_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } - else - Abc_ObjForEachFanin( pObj, pNext, i ) { - adj_dist = FDATA(pNext)->r_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } - - if (Abc_ObjIsLatch(pObj)) goto update; - - // 2. through - if (FTEST(pObj, FLOW)) { - adj_dist = FDATA(pObj)->r_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } - - // 3. reverse edges (backward retiming only) - if (!pManMR->fIsForward) { - Abc_ObjForEachFanout( pObj, pNext, i ) { - adj_dist = FDATA(pNext)->e_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } - - // 4. timing edges (backward retiming only) -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay) - Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) { - adj_dist = FDATA(pNext)->e_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } -#endif - } - - update: - ++min_dist; - if (min_dist >= MAX_DIST) min_dist = 0; - // printf("[%de=%d->%d] ", Abc_ObjId(pObj), old_dist, min_dist+1); - FDATA(pObj)->e_dist = min_dist; - - assert(min_dist < Vec_IntSize(pManMR->vSinkDistHist)); - h = Vec_IntArray(pManMR->vSinkDistHist); - h[old_dist]--; - h[min_dist]++; - if (!h[old_dist]) { - pManMR->fSinkDistTerminate = 1; - } -} - -void -dfsfast_r_retreat(Abc_Obj_t *pObj) { - Abc_Obj_t *pNext; - int i, *h; - int old_dist = FDATA(pObj)->r_dist; - int adj_dist, min_dist = MAX_DIST; - - // 1. through or pred - if (FTEST(pObj, FLOW)) { - if (FGETPRED(pObj)) { - adj_dist = FDATA(FGETPRED(pObj))->e_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } - } else { - adj_dist = FDATA(pObj)->e_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } - - // 2. reverse edges (forward retiming only) - if (pManMR->fIsForward) { - Abc_ObjForEachFanin( pObj, pNext, i ) - if (!Abc_ObjIsLatch(pNext)) { - adj_dist = FDATA(pNext)->r_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } - - // 3. timing edges (forward retiming only) -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay) - Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) { - adj_dist = FDATA(pNext)->r_dist; - if (adj_dist) min_dist = MIN(min_dist, adj_dist); - } -#endif - } - - ++min_dist; - if (min_dist >= MAX_DIST) min_dist = 0; - //printf("[%dr=%d->%d] ", Abc_ObjId(pObj), old_dist, min_dist+1); - FDATA(pObj)->r_dist = min_dist; - - assert(min_dist < Vec_IntSize(pManMR->vSinkDistHist)); - h = Vec_IntArray(pManMR->vSinkDistHist); - h[old_dist]--; - h[min_dist]++; - if (!h[old_dist]) { - pManMR->fSinkDistTerminate = 1; - } -} - -/**Function************************************************************* - - Synopsis [Plain DFS.] - - Description [Does not use sink-distance-histogram heuristic.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) { - int i; - Abc_Obj_t *pNext; - - if (FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask || - Abc_ObjIsPi(pObj)) { - assert(pPred); - assert(!pManMR->fIsForward); - return 1; - } - - FSET(pObj, VISITED_E); - - // printf(" %de\n", Abc_ObjId(pObj)); - - // 1. structural edges - if (pManMR->fIsForward) - Abc_ObjForEachFanout( pObj, pNext, i ) { - if (!FTEST(pNext, VISITED_R) && - dfsplain_r(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("o"); -#endif - goto found; - } - } - else - Abc_ObjForEachFanin( pObj, pNext, i ) { - if (!FTEST(pNext, VISITED_R) && - dfsplain_r(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("o"); -#endif - goto found; - } - } - - if (Abc_ObjIsLatch(pObj)) - return 0; - - // 2. reverse edges (backward retiming only) - if (!pManMR->fIsForward) { - Abc_ObjForEachFanout( pObj, pNext, i ) { - if (!FTEST(pNext, VISITED_E) && - dfsplain_e(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("i"); -#endif - goto found; - } - } - - // 3. timing edges (backward retiming only) -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay) - Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) { - if (!FTEST(pNext, VISITED_E) && - dfsplain_e(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("o"); -#endif - goto found; - } - } -#endif - } - - // unwind - if (FTEST(pObj, FLOW) && - !FTEST(pObj, VISITED_R) && - dfsplain_r(pObj, FGETPRED(pObj))) { - FUNSET(pObj, FLOW); - FSETPRED(pObj, NULL); -#ifdef DEBUG_PRINT_FLOWS - printf("u"); -#endif - goto found; - } - - return 0; - - found: -#ifdef DEBUG_PRINT_FLOWS - printf("%d ", Abc_ObjId(pObj)); -#endif - - return 1; -} - -int dfsplain_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) { - int i; - Abc_Obj_t *pNext, *pOldPred; - - // have we reached the sink? - if (Abc_ObjIsLatch(pObj) || - (pManMR->fIsForward && Abc_ObjIsPo(pObj)) || - (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) { - assert(pPred); - return 1; - } - - FSET(pObj, VISITED_R); - - // printf(" %dr\n", Abc_ObjId(pObj)); - - if (FTEST(pObj, FLOW)) { - - pOldPred = FGETPRED(pObj); - if (pOldPred && - !FTEST(pOldPred, VISITED_E) && - dfsplain_e(pOldPred, pOldPred)) { - - FSETPRED(pObj, pPred); - -#ifdef DEBUG_PRINT_FLOWS - printf("fr"); -#endif - goto found; - } - - } else { - - if (!FTEST(pObj, VISITED_E) && - dfsplain_e(pObj, pObj)) { - - FSET(pObj, FLOW); - FSETPRED(pObj, pPred); - -#ifdef DEBUG_PRINT_FLOWS - printf("f"); -#endif - goto found; - } - } - - // 2. follow reverse edges - if (pManMR->fIsForward) { // forward retiming only - Abc_ObjForEachFanin( pObj, pNext, i ) { - if (!FTEST(pNext, VISITED_R) && - !Abc_ObjIsLatch(pNext) && - dfsplain_r(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("i"); -#endif - goto found; - } - } - - // 3. timing edges (forward only) -#if !defined(IGNORE_TIMING) - if (pManMR->maxDelay) - Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) { - if (!FTEST(pNext, VISITED_R) && - dfsplain_r(pNext, pPred)) { -#ifdef DEBUG_PRINT_FLOWS - printf("o"); -#endif - goto found; - } - } -#endif - } - - return 0; - - found: -#ifdef DEBUG_PRINT_FLOWS - printf("%d ", Abc_ObjId(pObj)); -#endif - return 1; -} diff --git a/src/opt/fret/fretInit.c b/src/opt/fret/fretInit.c deleted file mode 100644 index 53df7386..00000000 --- a/src/opt/fret/fretInit.c +++ /dev/null @@ -1,762 +0,0 @@ -/**CFile**************************************************************** - - FileName [fretInit.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Flow-based retiming package.] - - Synopsis [Initialization for retiming package.] - - Author [Aaron Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2008.] - - Revision [$Id: fretInit.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "vec.h" -#include "io.h" -#include "fretime.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION PROTOTYPES /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ); -static void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk ); -static void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ); -static Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj, - Abc_Obj_t *pUseThisPi, Vec_Ptr_t *vOtherPis, - int recurse); -static void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ); -static void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ); - -extern void * Abc_FrameReadLibGen(); -extern Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Updates initial state information.] - - Description [Assumes latch boxes in original position, latches in - new positions.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk ) { - - if (!pManMR->fComputeInitState) return; - - if (pManMR->fIsForward) - Abc_FlowRetime_UpdateForwardInit( pNtk ); - else { - Abc_FlowRetime_UpdateBackwardInit( pNtk ); - } -} - - -/**Function************************************************************* - - Synopsis [Prints initial state information.] - - Description [Prints distribution of 0,1,and X initial states.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk ) { - int i, n0=0, n1=0, nDC=0, nOther=0; - Abc_Obj_t *pLatch; - - Abc_NtkForEachLatch( pNtk, pLatch, i ) { - if (Abc_LatchIsInit0(pLatch)) n0++; - else if (Abc_LatchIsInit1(pLatch)) n1++; - else if (Abc_LatchIsInitDc(pLatch)) nDC++; - else nOther++; - } - - printf("\tinitial states {0,1,x} = {%d, %d, %d}", n0, n1, nDC); - if (nOther) - printf(" + %d UNKNOWN", nOther); - printf("\n"); -} - - -/**Function************************************************************* - - Synopsis [Computes initial state after forward retiming.] - - Description [Assumes box outputs in old positions stored w/ init values. - Uses three-value simulation to preserve don't cares.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk ) { - Abc_Obj_t *pObj, *pFanin; - int i; - - vprintf("\t\tupdating init state\n"); - - Abc_NtkIncrementTravId( pNtk ); - - Abc_NtkForEachLatch( pNtk, pObj, i ) { - pFanin = Abc_ObjFanin0(pObj); - Abc_FlowRetime_UpdateForwardInit_rec( pFanin ); - - if (FTEST(pFanin, INIT_0)) - Abc_LatchSetInit0( pObj ); - else if (FTEST(pFanin, INIT_1)) - Abc_LatchSetInit1( pObj ); - else - Abc_LatchSetInitDc( pObj ); - } -} - -void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ) { - Abc_Obj_t *pNext; - int i; - - assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs - - if (Abc_ObjIsBo(pObj)) return; - - // visited? - if (Abc_NodeIsTravIdCurrent(pObj)) return; - Abc_NodeSetTravIdCurrent(pObj); - - Abc_ObjForEachFanin( pObj, pNext, i ) { - Abc_FlowRetime_UpdateForwardInit_rec( pNext ); - } - - Abc_FlowRetime_SimulateNode( pObj ); -} - - -/**Function************************************************************* - - Synopsis [Sets initial value flags.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_FlowRetime_SetInitValue( Abc_Obj_t * pObj, - int val, int dc ) { - - // store init value - FUNSET(pObj, INIT_CARE); - if (!dc){ - if (val) { - FSET(pObj, INIT_1); - } else { - FSET(pObj, INIT_0); - } - } -} - - -/**Function************************************************************* - - Synopsis [Propogates initial state through a logic node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ) { - Abc_Ntk_t *pNtk = Abc_ObjNtk(pObj); - Abc_Obj_t * pFanin; - int i, rAnd, rVar, dcAnd, dcVar; - DdManager * dd = pNtk->pManFunc; - DdNode *pBdd = pObj->pData, *pVar; - - assert(!Abc_ObjIsLatch(pObj)); - - // (i) constant nodes - if (Abc_NtkHasAig(pNtk) && Abc_AigNodeIsConst(pObj)) { - Abc_FlowRetime_SetInitValue(pObj, 1, 0); - return; - } - if (!Abc_NtkIsStrash( pNtk ) && Abc_ObjIsNode(pObj)) { - if (Abc_NodeIsConst0(pObj)) { - Abc_FlowRetime_SetInitValue(pObj, 0, 0); - return; - } else if (Abc_NodeIsConst1(pObj)) { - Abc_FlowRetime_SetInitValue(pObj, 1, 0); - return; - } - } - - // (ii) terminal nodes - if (!Abc_ObjIsNode(pObj)) { - pFanin = Abc_ObjFanin0(pObj); - - Abc_FlowRetime_SetInitValue(pObj, - (FTEST(pFanin, INIT_1) ? 1 : 0) ^ pObj->fCompl0, - !FTEST(pFanin, INIT_CARE)); - return; - } - - // (iii) logic nodes - - // ------ SOP network - if ( Abc_NtkHasSop( pNtk )) { - Abc_FlowRetime_SimulateSop( pObj, (char *)Abc_ObjData(pObj) ); - return; - } - - // ------ BDD network - else if ( Abc_NtkHasBdd( pNtk )) { - assert(dd); - assert(pBdd); - - // cofactor for 0,1 inputs - // do nothing for X values - Abc_ObjForEachFanin(pObj, pFanin, i) { - pVar = Cudd_bddIthVar( dd, i ); - if (FTEST(pFanin, INIT_CARE)) { - if (FTEST(pFanin, INIT_0)) - pBdd = Cudd_Cofactor( dd, pBdd, Cudd_Not(pVar) ); - else - pBdd = Cudd_Cofactor( dd, pBdd, pVar ); - } - } - - // if function has not been reduced to - // a constant, propagate an X - rVar = (pBdd == Cudd_ReadOne(dd)); - dcVar = !Cudd_IsConstant(pBdd); - - Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar); - return; - } - - // ------ AIG network - else if ( Abc_NtkHasAig( pNtk )) { - - assert(Abc_AigNodeIsAnd(pObj)); - dcAnd = 0, rAnd = 1; - - pFanin = Abc_ObjFanin0(pObj); - dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1; - rVar = FTEST(pFanin, INIT_0) ? 0 : 1; - if (pObj->fCompl0) rVar ^= 1; // complimented? - rAnd &= rVar; - - pFanin = Abc_ObjFanin1(pObj); - dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1; - rVar = FTEST(pFanin, INIT_0) ? 0 : 1; - if (pObj->fCompl1) rVar ^= 1; // complimented? - rAnd &= rVar; - - if (!rAnd) dcAnd = 0; /* controlling value */ - - Abc_FlowRetime_SetInitValue(pObj, rAnd, dcAnd); - return; - } - - // ------ MAPPED network - else if ( Abc_NtkHasMapping( pNtk )) { - Abc_FlowRetime_SimulateSop( pObj, (char *)Mio_GateReadSop(pObj->pData) ); - return; - } - - assert(0); -} - - -/**Function************************************************************* - - Synopsis [Propogates initial state through a SOP node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ) { - Abc_Obj_t * pFanin; - char *pCube; - int i, j, rAnd, rOr, rVar, dcAnd, dcOr, v; - - assert( pSop && !Abc_SopIsExorType(pSop) ); - - rOr = 0, dcOr = 0; - - i = Abc_SopGetVarNum(pSop); - Abc_SopForEachCube( pSop, i, pCube ) { - rAnd = 1, dcAnd = 0; - Abc_CubeForEachVar( pCube, v, j ) { - pFanin = Abc_ObjFanin(pObj, j); - if ( v == '0' ) - rVar = FTEST(pFanin, INIT_0) ? 1 : 0; - else if ( v == '1' ) - rVar = FTEST(pFanin, INIT_1) ? 1 : 0; - else - continue; - - if (FTEST(pFanin, INIT_CARE)) - rAnd &= rVar; - else - dcAnd = 1; - } - if (!rAnd) dcAnd = 0; /* controlling value */ - if (dcAnd) - dcOr = 1; - else - rOr |= rAnd; - } - if (rOr) dcOr = 0; /* controlling value */ - - // complement the result if necessary - if ( !Abc_SopGetPhase(pSop) ) - rOr ^= 1; - - Abc_FlowRetime_SetInitValue(pObj, rOr, dcOr); -} - -/**Function************************************************************* - - Synopsis [Sets up backward initial state computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) { - Abc_Obj_t *pLatch, *pObj, *pPi; - int i; - Vec_Ptr_t *vObj = Vec_PtrAlloc(100); - - // create the network used for the initial state computation - if (Abc_NtkHasMapping(pNtk)) - pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, ABC_FUNC_SOP, 1 ); - else - pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - - // mitre inputs - Abc_NtkForEachLatch( pNtk, pLatch, i ) { - // map latch to initial state network - pPi = Abc_NtkCreatePi( pManMR->pInitNtk ); - - // has initial state requirement? - if (Abc_LatchIsInit0(pLatch)) { - - if (Abc_NtkHasAig(pNtk)) - pObj = Abc_ObjNot( pPi ); - else - pObj = Abc_NtkCreateNodeInv( pManMR->pInitNtk, pPi ); - - Vec_PtrPush(vObj, pObj); - } - else if (Abc_LatchIsInit1(pLatch)) { - Vec_PtrPush(vObj, pPi); - } - - Abc_ObjSetData( pLatch, pPi ); // if not verifying init state - // FDATA(pLatch)->pInitObj = pPi; // if verifying init state - } - - // are there any nodes not DC? - if (!Vec_PtrSize(vObj)) { - pManMR->fSolutionIsDc = 1; - return; - } else - pManMR->fSolutionIsDc = 0; - - // mitre output - if (Abc_NtkHasAig(pNtk)) { - // create AND-by-AND - pObj = Vec_PtrPop( vObj ); - while( Vec_PtrSize(vObj) ) - pObj = Abc_AigAnd( pManMR->pInitNtk->pManFunc, pObj, Vec_PtrPop( vObj ) ); - } else - // create n-input AND gate - pObj = Abc_NtkCreateNodeAnd( pManMR->pInitNtk, vObj ); - - Abc_ObjAddFanin( Abc_NtkCreatePo( pManMR->pInitNtk ), pObj ); - - Vec_PtrFree( vObj ); -} - - -/**Function************************************************************* - - Synopsis [Solves backward initial state computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) { - int i; - Abc_Obj_t *pObj, *pInitObj; - Vec_Ptr_t *vDelete = Vec_PtrAlloc(0); - int result; - - assert(pManMR->pInitNtk); - - // is the solution entirely DC's? - if (pManMR->fSolutionIsDc) { - Abc_NtkDelete(pManMR->pInitNtk); - Vec_PtrFree(vDelete); - Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj ); - vprintf("\tno init state computation: all-don't-care solution\n"); - return 1; - } - - // check that network is combinational - // mark superfluous BI nodes for deletion - Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) { - assert(!Abc_ObjIsLatch(pObj)); - assert(!Abc_ObjIsBo(pObj)); - - if (Abc_ObjIsBi(pObj)) { - Abc_ObjBetterTransferFanout( pObj, Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); - Vec_PtrPush( vDelete, pObj ); - } - } - - // delete superfluous nodes - while(Vec_PtrSize( vDelete )) { - pObj = (Abc_Obj_t *)Vec_PtrPop( vDelete ); - Abc_NtkDeleteObj( pObj ); - } - Vec_PtrFree(vDelete); - - // do some final cleanup on the network - Abc_NtkAddDummyPoNames(pManMR->pInitNtk); - Abc_NtkAddDummyPiNames(pManMR->pInitNtk); - if (Abc_NtkIsLogic(pManMR->pInitNtk)) - Abc_NtkCleanup(pManMR->pInitNtk, 0); - else if (Abc_NtkIsStrash(pManMR->pInitNtk)) { - Abc_NtkReassignIds(pManMR->pInitNtk); - } - - vprintf("\tsolving for init state (%d nodes)... ", Abc_NtkObjNum(pManMR->pInitNtk)); - fflush(stdout); - - // convert SOPs to BDD - if (Abc_NtkHasSop(pManMR->pInitNtk)) - Abc_NtkSopToBdd( pManMR->pInitNtk ); - - // solve - result = Abc_NtkMiterSat( pManMR->pInitNtk, (sint64)500000, (sint64)50000000, 0, NULL, NULL ); - - if (!result) { - vprintf("SUCCESS\n"); - } else { - vprintf("FAILURE\n"); - printf("WARNING: no equivalent init state. setting all initial states to don't-cares\n"); - Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj ); - Abc_NtkDelete(pManMR->pInitNtk); - return 0; - } - - // clear initial values, associate PIs to latches - Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) Abc_ObjSetCopy( pInitObj, NULL ); - Abc_NtkForEachLatch( pNtk, pObj, i ) { - pInitObj = Abc_ObjData( pObj ); - assert( Abc_ObjIsPi( pInitObj )); - Abc_ObjSetCopy( pInitObj, pObj ); - Abc_LatchSetInitNone( pObj ); - } - - // copy solution from PIs to latches - assert(pManMR->pInitNtk->pModel); - Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) { - if ((pObj = Abc_ObjCopy( pInitObj ))) { - if ( pManMR->pInitNtk->pModel[i] ) - Abc_LatchSetInit1( pObj ); - else - Abc_LatchSetInit0( pObj ); - } - } - -#if defined(DEBUG_CHECK) - // check that all latches have initial state - Abc_NtkForEachLatch( pNtk, pObj, i ) assert( !Abc_LatchIsInitNone( pObj ) ); -#endif - - // deallocate - Abc_NtkDelete( pManMR->pInitNtk ); - - return 1; -} - - -/**Function************************************************************* - - Synopsis [Updates backward initial state computation problem.] - - Description [Assumes box outputs in old positions stored w/ init values.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) { - Abc_Obj_t *pOrigObj, *pInitObj; - Vec_Ptr_t *vBo = Vec_PtrAlloc(100); - Vec_Ptr_t *vOldPis = Vec_PtrAlloc(100); - int i; - - // remove PIs from network (from BOs) - Abc_NtkForEachObj( pNtk, pOrigObj, i ) - if (Abc_ObjIsBo(pOrigObj)) { - pInitObj = FDATA(pOrigObj)->pInitObj; - assert(Abc_ObjIsPi(pInitObj)); - Vec_PtrPush(vBo, pOrigObj); - - Abc_FlowRetime_UpdateBackwardInit_rec( Abc_ObjFanin0( pOrigObj ), pInitObj, vOldPis, 0 ); - } - - // add PIs to network (at latches) - Abc_NtkForEachLatch( pNtk, pOrigObj, i ) - Abc_FlowRetime_UpdateBackwardInit_rec( pOrigObj, NULL, vOldPis, 0 ); - - // connect nodes in init state network - Vec_PtrForEachEntry( vBo, pOrigObj, i ) - Abc_FlowRetime_UpdateBackwardInit_rec( Abc_ObjFanin0( pOrigObj ), NULL, NULL, 1 ); - - // clear flags - Abc_NtkForEachObj( pNtk, pOrigObj, i ) - pOrigObj->fMarkA = pOrigObj->fMarkB = 0; - - // deallocate - Vec_PtrFree( vBo ); - Vec_PtrFree( vOldPis ); -} - - -/**Function************************************************************* - - Synopsis [Updates backward initial state computation problem.] - - Description [Creates a duplicate node in the initial state network - corresponding to a node in the original circuit. If - fRecurse is set, the procedure recurses on and connects - the new node to its fan-ins. A latch in the original - circuit corresponds to a PI in the initial state network. - An existing PI may be supplied by pUseThisPi, and if the - node is a latch, it will be used; otherwise the PI is - saved in the list vOtherPis and subsequently used for - another latch.] - - SideEffects [Nodes that have a corresponding initial state node - are marked with fMarkA. Nodes that have been fully - connected in the initial state network are marked with - fMarkB.] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj, - Abc_Obj_t *pUseThisPi, Vec_Ptr_t *vOtherPis, - int fRecurse) { - Abc_Obj_t *pInitObj, *pOrigFanin, *pInitFanin; - void *pData; - int i; - Abc_Ntk_t *pNtk = Abc_ObjNtk( pOrigObj ); - - // should never reach primary IOs - assert(!Abc_ObjIsPi(pOrigObj)); - assert(!Abc_ObjIsPo(pOrigObj)); - - // if fanin is latch, it becomes a primary input - if (Abc_ObjIsLatch( pOrigObj )) { - if (pOrigObj->fMarkA) return FDATA(pOrigObj)->pInitObj; - - assert(vOtherPis); - - if (pUseThisPi) { - // reuse curent PI - pInitObj = pUseThisPi; } - else { - // reuse previous PI - pInitObj = (Abc_Obj_t*)Vec_PtrPop(vOtherPis); - } - - // remember link from original node to init ntk - Abc_ObjSetData( pOrigObj, pInitObj ); - - pOrigObj->fMarkA = 1; - return (FDATA(pOrigObj)->pInitObj = pInitObj); - } - - // does an init node already exist? - if(!pOrigObj->fMarkA) { - - if (Abc_NtkHasMapping( pNtk )) { - if (!pOrigObj->pData) { - // assume terminal... - assert(Abc_ObjFaninNum(pOrigObj) == 1); - pInitObj = Abc_NtkCreateNodeBuf( pManMR->pInitNtk, NULL ); - } else { - pInitObj = Abc_NtkCreateObj( pManMR->pInitNtk, Abc_ObjType(pOrigObj) ); - pData = Mio_GateReadSop(pOrigObj->pData); - assert( Abc_SopGetVarNum(pData) == Abc_ObjFaninNum(pOrigObj) ); - - pInitObj->pData = Abc_SopRegister( pManMR->pInitNtk->pManFunc, pData ); - } - } else { - pData = Abc_ObjCopy( pOrigObj ); // save ptr to flow data - if (Abc_NtkIsStrash( pNtk ) && Abc_AigNodeIsConst( pOrigObj )) - pInitObj = Abc_AigConst1( pManMR->pInitNtk ); - else - pInitObj = Abc_NtkDupObj( pManMR->pInitNtk, pOrigObj, 0 ); - Abc_ObjSetCopy( pOrigObj, pData ); // restore ptr to flow data - - // copy complementation - pInitObj->fCompl0 = pOrigObj->fCompl0; - pInitObj->fCompl1 = pOrigObj->fCompl1; - pInitObj->fPhase = pOrigObj->fPhase; - } - - // if we didn't use given PI, immediately transfer fanouts - // and add to list for later reuse - if (pUseThisPi) { - Abc_ObjBetterTransferFanout( pUseThisPi, pInitObj, 0 ); - Vec_PtrPush( vOtherPis, pUseThisPi ); - } - - pOrigObj->fMarkA = 1; - FDATA(pOrigObj)->pInitObj = pInitObj; - } else { - pInitObj = FDATA(pOrigObj)->pInitObj; - } - - // have we already connected this object? - if (fRecurse && !pOrigObj->fMarkB) { - - // create and/or connect fanins - Abc_ObjForEachFanin( pOrigObj, pOrigFanin, i ) { - pInitFanin = Abc_FlowRetime_UpdateBackwardInit_rec( pOrigFanin, NULL, NULL, fRecurse ); - Abc_ObjAddFanin( pInitObj, pInitFanin ); - } - - pOrigObj->fMarkB = 1; - } - - return pInitObj; -} - - -/**Function************************************************************* - - Synopsis [Verifies backward init state computation.] - - Description [This procedure requires the BOs to store the original - latch values and the latches to store the new values: - both in the INIT_0 and INIT_1 flags in the Flow_Data - structure. (This is not currently the case in the rest - of the code.) Also, can not verify backward state - computations that span multiple combinational frames.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk ) { - Abc_Obj_t *pObj, *pFanin; - int i; - - vprintf("\t\tupdating init state\n"); - - Abc_NtkIncrementTravId( pNtk ); - - Abc_NtkForEachObj( pNtk, pObj, i ) - if (Abc_ObjIsBo( pObj )) { - pFanin = Abc_ObjFanin0(pObj); - Abc_FlowRetime_VerifyBackwardInit_rec( pFanin ); - - if (FTEST(pObj, INIT_CARE)) { - if(FTEST(pObj, INIT_CARE) != FTEST(pFanin, INIT_CARE)) { - printf("ERROR: expected val=%d care=%d and got val=%d care=%d\n", - FTEST(pObj, INIT_1)?1:0, FTEST(pObj, INIT_CARE)?1:0, - FTEST(pFanin, INIT_1)?1:0, FTEST(pFanin, INIT_CARE)?1:0 ); - - } - } - } -} - -void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ) { - Abc_Obj_t *pNext; - int i; - - assert(!Abc_ObjIsBo(pObj)); // should never reach the inputs - assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs - - // visited? - if (Abc_NodeIsTravIdCurrent(pObj)) return; - Abc_NodeSetTravIdCurrent(pObj); - - if (Abc_ObjIsLatch(pObj)) { - FUNSET(pObj, INIT_CARE); - if (Abc_LatchIsInit0(pObj)) - FSET(pObj, INIT_0); - else if (Abc_LatchIsInit1(pObj)) - FSET(pObj, INIT_1); - return; - } - - Abc_ObjForEachFanin( pObj, pNext, i ) { - Abc_FlowRetime_VerifyBackwardInit_rec( pNext ); - } - - Abc_FlowRetime_SimulateNode( pObj ); -} - - -/**Function************************************************************* - - Synopsis [Constrains backward retiming for initializability.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_ConstrainInit( ) { - // unimplemented -} diff --git a/src/opt/fret/fretMain.c b/src/opt/fret/fretMain.c deleted file mode 100644 index 780c1f6f..00000000 --- a/src/opt/fret/fretMain.c +++ /dev/null @@ -1,1059 +0,0 @@ -/**CFile**************************************************************** - - FileName [fretMain.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Flow-based retiming package.] - - Synopsis [Main file for retiming package.] - - Author [Aaron Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2008.] - - Revision [$Id: fretMain.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "vec.h" -#include "fretime.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj ); - -static void Abc_FlowRetime_MainLoop( ); - -static void Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ); -static void Abc_FlowRetime_MarkReachable_rec( Abc_Obj_t * pObj, char end ); -static int Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ); -static void Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch ); - -static void Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk ); -static int Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD ); - -extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ); -extern Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ); - -void -print_node3(Abc_Obj_t *pObj); - -MinRegMan_t *pManMR; - -int fPathError = 0; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs minimum-register retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * -Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState, - int fForwardOnly, int fBackwardOnly, int nMaxIters, - int maxDelay, int fFastButConservative ) { - - int i; - Abc_Obj_t *pObj, *pNext; - - // create manager - pManMR = ALLOC( MinRegMan_t, 1 ); - - pManMR->pNtk = pNtk; - pManMR->fVerbose = fVerbose; - pManMR->fComputeInitState = fComputeInitState; - pManMR->fGuaranteeInitState = 0; - pManMR->fForwardOnly = fForwardOnly; - pManMR->fBackwardOnly = fBackwardOnly; - pManMR->nMaxIters = nMaxIters; - pManMR->maxDelay = maxDelay; - pManMR->fComputeInitState = fComputeInitState; - pManMR->fConservTimingOnly = fFastButConservative; - pManMR->vNodes = Vec_PtrAlloc(100); - - vprintf("Flow-based minimum-register retiming...\n"); - - if (!Abc_NtkHasOnlyLatchBoxes(pNtk)) { - printf("\tERROR: Can not retime with black/white boxes\n"); - return pNtk; - } - - if (maxDelay) { - vprintf("\tmax delay constraint = %d\n", maxDelay); - if (maxDelay < (i = Abc_NtkLevel(pNtk))) { - printf("ERROR: max delay constraint must be > current max delay (%d)\n", i); - return pNtk; - } - } - - // print info about type of network - vprintf("\tnetlist type = "); - if (Abc_NtkIsNetlist( pNtk )) { vprintf("netlist/"); } - else if (Abc_NtkIsLogic( pNtk )) { vprintf("logic/"); } - else if (Abc_NtkIsStrash( pNtk )) { vprintf("strash/"); } - else { vprintf("***unknown***/"); } - if (Abc_NtkHasSop( pNtk )) { vprintf("sop\n"); } - else if (Abc_NtkHasBdd( pNtk )) { vprintf("bdd\n"); } - else if (Abc_NtkHasAig( pNtk )) { vprintf("aig\n"); } - else if (Abc_NtkHasMapping( pNtk )) { vprintf("mapped\n"); } - else { vprintf("***unknown***\n"); } - - vprintf("\tinitial reg count = %d\n", Abc_NtkLatchNum(pNtk)); - vprintf("\tinitial levels = %d\n", Abc_NtkLevel(pNtk)); - - // remove bubbles from latch boxes - if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk); - vprintf("\tpushing bubbles out of latch boxes\n"); - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_FlowRetime_RemoveLatchBubbles(pObj); - if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk); - - // check for box inputs/outputs - Abc_NtkForEachLatch( pNtk, pObj, i ) { - assert(Abc_ObjFaninNum(pObj) == 1); - assert(Abc_ObjFanoutNum(pObj) == 1); - assert(!Abc_ObjFaninC0(pObj)); - - pNext = Abc_ObjFanin0(pObj); - assert(Abc_ObjIsBi(pNext)); - assert(Abc_ObjFaninNum(pNext) <= 1); - if(Abc_ObjFaninNum(pNext) == 0) // every Bi should have a fanin - Abc_FlowRetime_AddDummyFanin( pNext ); - - pNext = Abc_ObjFanout0(pObj); - assert(Abc_ObjIsBo(pNext)); - assert(Abc_ObjFaninNum(pNext) == 1); - assert(!Abc_ObjFaninC0(pNext)); - } - - pManMR->nLatches = Abc_NtkLatchNum( pNtk ); - pManMR->nNodes = Abc_NtkObjNumMax( pNtk )+1; - - // build histogram - pManMR->vSinkDistHist = Vec_IntStart( pManMR->nNodes*2+10 ); - - // initialize timing - if (maxDelay) - Abc_FlowRetime_InitTiming( pNtk ); - - // create Flow_Data structure - pManMR->pDataArray = ALLOC( Flow_Data_t, pManMR->nNodes ); - Abc_FlowRetime_ClearFlows( 1 ); - Abc_NtkForEachObj( pNtk, pObj, i ) - Abc_ObjSetCopy( pObj, (void *)(&pManMR->pDataArray[i]) ); - - // main loop! - Abc_FlowRetime_MainLoop(); - - // clear pCopy field - Abc_NtkForEachObj( pNtk, pObj, i ) { - Abc_ObjSetCopy( pObj, NULL ); - - // if not computing init state, set all latches to DC - if (!fComputeInitState && Abc_ObjIsLatch(pObj)) - Abc_LatchSetInitDc(pObj); - } - - // deallocate space - FREE( pManMR->pDataArray ); - if (pManMR->vNodes) Vec_PtrFree(pManMR->vNodes); - if (pManMR->vSinkDistHist) Vec_IntFree(pManMR->vSinkDistHist); - if (pManMR->maxDelay) Abc_FlowRetime_FreeTiming( pNtk ); - - // restrash if necessary - if (Abc_NtkIsStrash(pNtk)) { - Abc_NtkReassignIds( pNtk ); - pNtk = Abc_NtkRestrash( pNtk, 1 ); - } - - vprintf("\tfinal reg count = %d\n", Abc_NtkLatchNum(pNtk)); - vprintf("\tfinal levels = %d\n", Abc_NtkLevel(pNtk)); - -#if defined(DEBUG_CHECK) - Abc_NtkDoCheck( pNtk ); -#endif - - // free manager - FREE( pManMR ); - - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Main loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_MainLoop( ) { - Abc_Ntk_t *pNtk = pManMR->pNtk; - // Abc_Obj_t *pObj; int i; - int last, flow = 0, cut; - - // (i) forward retiming loop - pManMR->fIsForward = 1; - pManMR->iteration = 0; - - if (!pManMR->fBackwardOnly) do { - if (pManMR->iteration == pManMR->nMaxIters) break; - pManMR->subIteration = 0; - - vprintf("\tforward iteration %d\n", pManMR->iteration); - last = Abc_NtkLatchNum( pNtk ); - - Abc_FlowRetime_MarkBlocks( pNtk ); - - if (pManMR->maxDelay) { - // timing-constrained loop - Abc_FlowRetime_ConstrainConserv( pNtk ); - while(Abc_FlowRetime_RefineConstraints( )) { - pManMR->subIteration++; - Abc_FlowRetime_ClearFlows( 0 ); - } - } else { - flow = Abc_FlowRetime_PushFlows( pNtk, 1 ); - } - - cut = Abc_FlowRetime_ImplementCut( pNtk ); - - vprintf("\t\tlevels = %d\n", Abc_NtkLevel(pNtk)); - -#if 0 - Abc_NtkForEachObj( pNtk, pObj, i ) pObj->Level = 0; - - Abc_NtkLevel(pNtk); - Abc_NtkForEachObj( pNtk, pObj, i ) - if (pObj->Level > pManMR->maxDelay) { - print_node( pObj ); - Vec_PtrForEachEntry( FTIMEEDGES(pObj), p2,j ) { - printf(":%d ", p2->Id); - } - } - Abc_NtkLevelReverse(pNtk); - Abc_NtkForEachObj( pNtk, pObj, i ) - if (pObj->Level > pManMR->maxDelay) { - print_node( pObj ); - } -#endif - - Abc_FlowRetime_ClearFlows( 1 ); - - pManMR->iteration++; - } while( cut != last ); - - // print info about initial states - if (pManMR->fComputeInitState && pManMR->fVerbose) - Abc_FlowRetime_PrintInitStateInfo( pNtk ); - - // (ii) backward retiming loop - pManMR->fIsForward = 0; - pManMR->iteration = 0; - - if (!pManMR->fForwardOnly) do { - // initializability loop - - if (pManMR->fComputeInitState) { - Abc_FlowRetime_SetupBackwardInit( pNtk ); - } - - do { - if (pManMR->iteration == pManMR->nMaxIters) break; - pManMR->subIteration = 0; - - vprintf("\tbackward iteration %d\n", pManMR->iteration); - last = Abc_NtkLatchNum( pNtk ); - - Abc_FlowRetime_MarkBlocks( pNtk ); - - if (pManMR->maxDelay) { - // timing-constrained loop - Abc_FlowRetime_ConstrainConserv( pNtk ); - while(Abc_FlowRetime_RefineConstraints( )) { - pManMR->subIteration++; - Abc_FlowRetime_ClearFlows( 0 ); - } - } else { - flow = Abc_FlowRetime_PushFlows( pNtk, 1 ); - } - - cut = Abc_FlowRetime_ImplementCut( pNtk ); - - vprintf("\t\tlevels = %d\n", Abc_NtkLevelReverse(pNtk)); - -#if 0 - Abc_NtkForEachObj( pNtk, pObj, i ) pObj->Level = 0; - - Abc_NtkLevel(pNtk); - Abc_NtkForEachObj( pNtk, pObj, i ) - if (pObj->Level > pManMR->maxDelay) { - print_node( pObj ); - } - Abc_NtkLevelReverse(pNtk); - Abc_NtkForEachObj( pNtk, pObj, i ) - if (pObj->Level > pManMR->maxDelay) { - print_node( pObj ); - } -#endif - - Abc_FlowRetime_ClearFlows( 1 ); - - pManMR->iteration++; - } while( cut != last ); - - // compute initial states - if (!pManMR->fComputeInitState) break; - - if (Abc_FlowRetime_SolveBackwardInit( pNtk )) { - if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo( pNtk ); - break; - } else { - if (!pManMR->fGuaranteeInitState) break; - Abc_FlowRetime_ConstrainInit( ); - } - } while(1); -} - - -/**Function************************************************************* - - Synopsis [Pushes latch bubbles outside of box.] - - Description [If network is an AIG, a fCompl0 is allowed to remain on - the BI node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch ) { - int bubble = 0; - Abc_Ntk_t *pNtk = pManMR->pNtk; - Abc_Obj_t *pBi, *pBo, *pInv; - - pBi = Abc_ObjFanin0(pLatch); - pBo = Abc_ObjFanout0(pLatch); - assert(!Abc_ObjIsComplement(pBi)); - assert(!Abc_ObjIsComplement(pBo)); - - // push bubbles on BO into latch box - if (Abc_ObjFaninC0(pBo) && Abc_ObjFanoutNum(pBo) > 0) { - bubble = 1; - if (Abc_LatchIsInit0(pLatch)) Abc_LatchSetInit1(pLatch); - else if (Abc_LatchIsInit1(pLatch)) Abc_LatchSetInit0(pLatch); - } - - // absorb bubbles on BI - pBi->fCompl0 ^= bubble ^ Abc_ObjFaninC0(pLatch); - - // convert bubble to INV if not AIG - if (!Abc_NtkHasAig( pNtk ) && Abc_ObjFaninC0(pBi)) { - pBi->fCompl0 = 0; - pInv = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanin0(pBi) ); - Abc_ObjPatchFanin( pBi, Abc_ObjFanin0(pBi), pInv ); - } - - pBo->fCompl0 = 0; - pLatch->fCompl0 = 0; -} - - -/**Function************************************************************* - - Synopsis [Marks nodes in TFO/TFI of PI/PO.] - - Description [Sets flow data flag BLOCK appropriately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ) { - int i; - Abc_Obj_t *pObj; - - if (pManMR->fIsForward){ - // mark the frontier - Abc_NtkForEachPo( pNtk, pObj, i ) - pObj->fMarkA = 1; - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - pObj->fMarkA = 1; - } - // mark the nodes reachable from the PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward ); - } else { - // mark the frontier - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->fMarkA = 1; - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - pObj->fMarkA = 1; - } - // mark the nodes reachable from the POs - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward ); - } - - // copy marks - Abc_NtkForEachObj( pNtk, pObj, i ) { - if (pObj->fMarkA) { - pObj->fMarkA = 0; - if (!Abc_ObjIsLatch(pObj) /* && !Abc_ObjIsPi(pObj) */ ) - FSET(pObj, BLOCK); - } - } -} - - -/**Function************************************************************* - - Synopsis [Computes maximum flow.] - - Description [] - - SideEffects [Leaves VISITED flags on source-reachable nodes.] - - SeeAlso [] - -***********************************************************************/ -int -Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, bool fVerbose ) { - int i, j, flow = 0, last, srcDist = 0; - Abc_Obj_t *pObj, *pObj2; - - pManMR->constraintMask |= BLOCK; - - pManMR->fSinkDistTerminate = 0; - dfsfast_preorder( pNtk ); - - // (i) fast max-flow computation - while(!pManMR->fSinkDistTerminate && srcDist < MAX_DIST) { - srcDist = MAX_DIST; - Abc_NtkForEachLatch( pNtk, pObj, i ) - if (FDATA(pObj)->e_dist) - srcDist = MIN(srcDist, FDATA(pObj)->e_dist); - - Abc_NtkForEachLatch( pNtk, pObj, i ) { - if (srcDist == FDATA(pObj)->e_dist && - dfsfast_e( pObj, NULL )) { -#ifdef DEBUG_PRINT_FLOWS - printf("\n\n"); -#endif - flow++; - } - } - } - - if (fVerbose) vprintf("\t\tmax-flow1 = %d \t", flow); - - // (ii) complete max-flow computation - // also, marks source-reachable nodes - do { - last = flow; - Abc_NtkForEachLatch( pNtk, pObj, i ) { - if (dfsplain_e( pObj, NULL )) { -#ifdef DEBUG_PRINT_FLOWS - printf("\n\n"); -#endif - flow++; - Abc_NtkForEachObj( pNtk, pObj2, j ) - FUNSET( pObj2, VISITED ); - } - } - } while (flow > last); - - if (fVerbose) vprintf("max-flow2 = %d\n", flow); - - return flow; -} - - -/**Function************************************************************* - - Synopsis [Restores latch boxes.] - - Description [Latchless BI/BO nodes are removed. Latch boxes are - restored around remaining latches.] - - SideEffects [Deletes nodes as appropriate.] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_FixLatchBoxes( Abc_Ntk_t *pNtk, Vec_Ptr_t *vBoxIns ) { - int i; - Abc_Obj_t *pObj, *pBo = NULL, *pBi = NULL; - Vec_Ptr_t *vFreeBi = Vec_PtrAlloc( 100 ); - Vec_Ptr_t *vFreeBo = Vec_PtrAlloc( 100 ); - - // 1. remove empty bi/bo pairs - while(Vec_PtrSize( vBoxIns )) { - pBi = (Abc_Obj_t *)Vec_PtrPop( vBoxIns ); - assert(Abc_ObjIsBi(pBi)); - assert(Abc_ObjFanoutNum(pBi) == 1); - assert(Abc_ObjFaninNum(pBi) == 1); - pBo = Abc_ObjFanout0(pBi); - assert(!Abc_ObjFaninC0(pBo)); - - if (Abc_ObjIsBo(pBo)) { - // an empty bi/bo pair - - Abc_ObjRemoveFanins( pBo ); - // transfer complement from BI, if present - assert(!Abc_ObjIsComplement(Abc_ObjFanin0(pBi))); - Abc_ObjBetterTransferFanout( pBo, Abc_ObjFanin0(pBi), Abc_ObjFaninC0(pBi) ); - - Abc_ObjRemoveFanins( pBi ); - pBi->fCompl0 = 0; - Vec_PtrPush( vFreeBi, pBi ); - Vec_PtrPush( vFreeBo, pBo ); - - // free names - if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pBi))) - Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pBi)); - if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pBo))) - Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pBo)); - - // check for complete detachment - assert(Abc_ObjFaninNum(pBi) == 0); - assert(Abc_ObjFanoutNum(pBi) == 0); - assert(Abc_ObjFaninNum(pBo) == 0); - assert(Abc_ObjFanoutNum(pBo) == 0); - } else assert(Abc_ObjIsLatch(pBo)); - } - - // 2. add bi/bos as necessary for latches - Abc_NtkForEachLatch( pNtk, pObj, i ) { - assert(Abc_ObjFaninNum(pObj) == 1); - if (Abc_ObjFanoutNum(pObj)) - pBo = Abc_ObjFanout0(pObj); - else pBo = NULL; - pBi = Abc_ObjFanin0(pObj); - - // add BO - if (!pBo || !Abc_ObjIsBo(pBo)) { - pBo = (Abc_Obj_t *)Vec_PtrPop( vFreeBo ); - if (Abc_ObjFanoutNum(pObj)) Abc_ObjTransferFanout( pObj, pBo ); - Abc_ObjAddFanin( pBo, pObj ); - } - // add BI - if (!Abc_ObjIsBi(pBi)) { - pBi = (Abc_Obj_t *)Vec_PtrPop( vFreeBi ); - assert(Abc_ObjFaninNum(pBi) == 0); - Abc_ObjAddFanin( pBi, Abc_ObjFanin0(pObj) ); - pBi->fCompl0 = pObj->fCompl0; - Abc_ObjRemoveFanins( pObj ); - Abc_ObjAddFanin( pObj, pBi ); - } - } - - // delete remaining BIs and BOs - while(Vec_PtrSize( vFreeBi )) { - pObj = (Abc_Obj_t *)Vec_PtrPop( vFreeBi ); - Abc_NtkDeleteObj( pObj ); - } - while(Vec_PtrSize( vFreeBo )) { - pObj = (Abc_Obj_t *)Vec_PtrPop( vFreeBo ); - Abc_NtkDeleteObj( pObj ); - } - -#if defined(DEBUG_CHECK) - Abc_NtkForEachObj( pNtk, pObj, i ) { - if (Abc_ObjIsBo(pObj)) { - assert(Abc_ObjFaninNum(pObj) == 1); - assert(Abc_ObjIsLatch(Abc_ObjFanin0(pObj))); - } - if (Abc_ObjIsBi(pObj)) { - assert(Abc_ObjFaninNum(pObj) == 1); - assert(Abc_ObjFanoutNum(pObj) == 1); - assert(Abc_ObjIsLatch(Abc_ObjFanout0(pObj))); - } - if (Abc_ObjIsLatch(pObj)) { - assert(Abc_ObjFanoutNum(pObj) == 1); - assert(Abc_ObjFaninNum(pObj) == 1); - } - } -#endif - - Vec_PtrFree( vFreeBi ); - Vec_PtrFree( vFreeBo ); -} - - -/**Function************************************************************* - - Synopsis [Checks register count along all combinational paths.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk ) { - int i; - Abc_Obj_t *pObj; - fPathError = 0; - - vprintf("\t\tVerifying latency along all paths..."); - - Abc_NtkForEachObj( pNtk, pObj, i ) { - if (Abc_ObjIsBo(pObj)) { - Abc_FlowRetime_VerifyPathLatencies_rec( pObj, 0 ); - } else if (!pManMR->fIsForward && Abc_ObjIsPi(pObj)) { - Abc_FlowRetime_VerifyPathLatencies_rec( pObj, 0 ); - } - - if (fPathError) { - if (Abc_ObjFaninNum(pObj) > 0) { - printf("fanin "); - print_node(Abc_ObjFanin0(pObj)); - } - printf("\n"); - exit(0); - } - } - - vprintf(" ok\n"); - - Abc_NtkForEachObj( pNtk, pObj, i ) { - pObj->fMarkA = 0; - pObj->fMarkB = 0; - pObj->fMarkC = 0; - } -} - - -int -Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD ) { - int i, j; - Abc_Obj_t *pNext; - int fCare = 0; - int markC = pObj->fMarkC; - - if (!pObj->fMarkB) { - pObj->fMarkB = 1; // visited - - if (Abc_ObjIsLatch(pObj)) - markC = 1; // latch in output - - if (!pManMR->fIsForward && !Abc_ObjIsPo(pObj) && !Abc_ObjFanoutNum(pObj)) - return -1; // dangling non-PO outputs : don't care what happens - - Abc_ObjForEachFanout( pObj, pNext, i ) { - // reached end of cycle? - if ( Abc_ObjIsBo(pNext) || - (pManMR->fIsForward && Abc_ObjIsPo(pNext)) ) { - if (!markD && !Abc_ObjIsLatch(pObj)) { - printf("\nERROR: no-latch path (end)\n"); - print_node(pNext); - printf("\n"); - fPathError = 1; - } - } else if (!pManMR->fIsForward && Abc_ObjIsPo(pNext)) { - if (markD || Abc_ObjIsLatch(pObj)) { - printf("\nERROR: extra-latch path to outputs\n"); - print_node(pNext); - printf("\n"); - fPathError = 1; - } - } else { - j = Abc_FlowRetime_VerifyPathLatencies_rec( pNext, markD || Abc_ObjIsLatch(pObj) ); - if (j >= 0) { - markC |= j; - fCare = 1; - } - } - - if (fPathError) { - print_node(pObj); - printf("\n"); - return 0; - } - } - } - - if (!fCare) return -1; - - if (markC && markD) { - printf("\nERROR: mult-latch path\n"); - print_node(pObj); - printf("\n"); - fPathError = 1; - } - if (!markC && !markD) { - printf("\nERROR: no-latch path (inter)\n"); - print_node(pObj); - printf("\n"); - fPathError = 1; - } - - return (pObj->fMarkC = markC); -} - - -/**Function************************************************************* - - Synopsis [Copies initial state from latches to BO nodes.] - - Description [Initial states are marked on BO nodes with INIT_0 and - INIT_1 flags in their Flow_Data structures.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_CopyInitState( Abc_Obj_t * pSrc, Abc_Obj_t * pDest ) { - Abc_Obj_t *pObj; - - if (!pManMR->fComputeInitState) return; - - assert(Abc_ObjIsLatch(pSrc)); - assert(Abc_ObjFanin0(pDest) == pSrc); - assert(!Abc_ObjFaninC0(pDest)); - - FUNSET(pDest, INIT_CARE); - if (Abc_LatchIsInit0(pSrc)) { - FSET(pDest, INIT_0); - } else if (Abc_LatchIsInit1(pSrc)) { - FSET(pDest, INIT_1); - } - - if (!pManMR->fIsForward) { - pObj = Abc_ObjData(pSrc); - assert(Abc_ObjIsPi(pObj)); - FDATA(pDest)->pInitObj = pObj; - } -} - - -/**Function************************************************************* - - Synopsis [Implements min-cut.] - - Description [Requires source-reachable nodes to be marked VISITED.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int -Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ) { - int i, j, cut = 0, unmoved = 0; - Abc_Obj_t *pObj, *pReg, *pNext, *pBo = NULL, *pBi = NULL; - Vec_Ptr_t *vFreeRegs = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); - Vec_Ptr_t *vBoxIns = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); - Vec_Ptr_t *vMove = Vec_PtrAlloc( 100 ); - - // remove latches from netlist - Abc_NtkForEachLatch( pNtk, pObj, i ) { - pBo = Abc_ObjFanout0(pObj); - pBi = Abc_ObjFanin0(pObj); - assert(Abc_ObjIsBo(pBo) && Abc_ObjIsBi(pBi)); - Vec_PtrPush( vBoxIns, pBi ); - - // copy initial state values to BO - Abc_FlowRetime_CopyInitState( pObj, pBo ); - - // re-use latch elsewhere - Vec_PtrPush( vFreeRegs, pObj ); - FSET(pBo, CROSS_BOUNDARY); - - // cut out of netlist - Abc_ObjPatchFanin( pBo, pObj, pBi ); - Abc_ObjRemoveFanins( pObj ); - - // free name - if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pObj))) - Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pObj)); - } - - // insert latches into netlist - Abc_NtkForEachObj( pNtk, pObj, i ) { - if (Abc_ObjIsLatch( pObj )) continue; - - // a latch is required on every node that lies across the min-cit - assert(!pManMR->fIsForward || !FTEST(pObj, VISITED_E) || FTEST(pObj, VISITED_R)); - if (FTEST(pObj, VISITED_R) && !FTEST(pObj, VISITED_E)) { - assert(FTEST(pObj, FLOW)); - - // count size of cut - cut++; - if ((pManMR->fIsForward && Abc_ObjIsBo(pObj)) || - (!pManMR->fIsForward && Abc_ObjIsBi(pObj))) - unmoved++; - - // only insert latch between fanouts that lie across min-cut - // some fanout paths may be cut at deeper points - Abc_ObjForEachFanout( pObj, pNext, j ) - if (Abc_FlowRetime_IsAcrossCut( pObj, pNext )) - Vec_PtrPush(vMove, pNext); - - // check that move-set is non-zero - if (Vec_PtrSize(vMove) == 0) - print_node(pObj); - assert(Vec_PtrSize(vMove) > 0); - - // insert one of re-useable registers - assert(Vec_PtrSize( vFreeRegs )); - pReg = (Abc_Obj_t *)Vec_PtrPop( vFreeRegs ); - - Abc_ObjAddFanin(pReg, pObj); - while(Vec_PtrSize( vMove )) { - pNext = (Abc_Obj_t *)Vec_PtrPop( vMove ); - Abc_ObjPatchFanin( pNext, pObj, pReg ); - if (Abc_ObjIsBi(pNext)) assert(Abc_ObjFaninNum(pNext) == 1); - - } - if (Abc_ObjIsBi(pObj)) assert(Abc_ObjFaninNum(pObj) == 1); - } - } - -#if defined(DEBUG_CHECK) - Abc_FlowRetime_VerifyPathLatencies( pNtk ); -#endif - - // delete remaining latches - while(Vec_PtrSize( vFreeRegs )) { - pReg = (Abc_Obj_t *)Vec_PtrPop( vFreeRegs ); - Abc_NtkDeleteObj( pReg ); - } - - // update initial states - Abc_FlowRetime_InitState( pNtk ); - - // restore latch boxes - Abc_FlowRetime_FixLatchBoxes( pNtk, vBoxIns ); - - Vec_PtrFree( vFreeRegs ); - Vec_PtrFree( vMove ); - Vec_PtrFree( vBoxIns ); - - vprintf("\t\tmin-cut = %d (unmoved = %d)\n", cut, unmoved); - return cut; -} - - -/**Function************************************************************* - - Synopsis [Adds dummy fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj ) { - Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj ); - - if (Abc_NtkHasAig(pNtk)) - Abc_ObjAddFanin(pObj, Abc_AigConst1( pNtk )); - else - Abc_ObjAddFanin(pObj, Abc_NtkCreateNodeConst0( pNtk )); -} - - -/**Function************************************************************* - - Synopsis [Prints information about a node.] - - Description [Debuging.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -print_node(Abc_Obj_t *pObj) { - int i; - Abc_Obj_t * pNext; - char m[6]; - - m[0] = 0; - if (pObj->fMarkA) - strcat(m, "A"); - if (pObj->fMarkB) - strcat(m, "B"); - if (pObj->fMarkC) - strcat(m, "C"); - - printf("node %d type=%d lev=%d tedge=%d (%x%s) fanouts {", Abc_ObjId(pObj), Abc_ObjType(pObj), - pObj->Level, Vec_PtrSize(FTIMEEDGES(pObj)), FDATA(pObj)->mark, m); - Abc_ObjForEachFanout( pObj, pNext, i ) - printf("%d[%d](%d),", Abc_ObjId(pNext), Abc_ObjType(pNext), FDATA(pNext)->mark); - printf("} fanins {"); - Abc_ObjForEachFanin( pObj, pNext, i ) - printf("%d[%d](%d),", Abc_ObjId(pNext), Abc_ObjType(pNext), FDATA(pNext)->mark); - printf("}\n"); -} - -void -print_node2(Abc_Obj_t *pObj) { - int i; - Abc_Obj_t * pNext; - char m[6]; - - m[0] = 0; - if (pObj->fMarkA) - strcat(m, "A"); - if (pObj->fMarkB) - strcat(m, "B"); - if (pObj->fMarkC) - strcat(m, "C"); - - printf("node %d type=%d %s fanouts {", Abc_ObjId(pObj), Abc_ObjType(pObj), m); - Abc_ObjForEachFanout( pObj, pNext, i ) - printf("%d ,", Abc_ObjId(pNext)); - printf("} fanins {"); - Abc_ObjForEachFanin( pObj, pNext, i ) - printf("%d ,", Abc_ObjId(pNext)); - printf("} "); -} - -void -print_node3(Abc_Obj_t *pObj) { - int i; - Abc_Obj_t * pNext; - char m[6]; - - m[0] = 0; - if (pObj->fMarkA) - strcat(m, "A"); - if (pObj->fMarkB) - strcat(m, "B"); - if (pObj->fMarkC) - strcat(m, "C"); - - printf("\nnode %d type=%d mark=%d %s\n", Abc_ObjId(pObj), Abc_ObjType(pObj), FDATA(pObj)->mark, m); - printf("fanouts\n"); - Abc_ObjForEachFanout( pObj, pNext, i ) { - print_node(pNext); - printf("\n"); - } - printf("fanins\n"); - Abc_ObjForEachFanin( pObj, pNext, i ) { - print_node(pNext); - printf("\n"); - } -} - - -/**Function************************************************************* - - Synopsis [Transfers fanout.] - - Description [Does not produce an error if there is no fanout. - Complements as necessary.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_ObjBetterTransferFanout( Abc_Obj_t * pFrom, Abc_Obj_t * pTo, int compl ) { - Abc_Obj_t *pNext; - - while(Abc_ObjFanoutNum(pFrom) > 0) { - pNext = Abc_ObjFanout0(pFrom); - Abc_ObjPatchFanin( pNext, pFrom, Abc_ObjNotCond(pTo, compl) ); - } -} - - -/**Function************************************************************* - - Synopsis [Returns true is a connection spans the min-cut.] - - Description [pNext is a direct fanout of pObj.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool -Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pObj, Abc_Obj_t *pNext ) { - - if (FTEST(pObj, VISITED_R) && !FTEST(pObj, VISITED_E)) { - if (pManMR->fIsForward) { - if (!FTEST(pNext, VISITED_R) || - (FTEST(pNext, BLOCK_OR_CONS) & pManMR->constraintMask)|| - FTEST(pNext, CROSS_BOUNDARY) || - Abc_ObjIsLatch(pNext)) - return 1; - } else { - if (FTEST(pNext, VISITED_E) || - FTEST(pNext, CROSS_BOUNDARY)) - return 1; - } - } - - return 0; -} - - -/**Function************************************************************* - - Synopsis [Resets flow problem] - - Description [If fClearAll is true, all marks will be cleared; this is - typically appropriate after the circuit structure has - been modified.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_ClearFlows( bool fClearAll ) { - int i; - - if (fClearAll) - memset(pManMR->pDataArray, 0, sizeof(Flow_Data_t)*pManMR->nNodes); - else { - // clear only data related to flow problem - for(i=0; inNodes; i++) { - pManMR->pDataArray[i].mark &= ~(VISITED | FLOW ); - pManMR->pDataArray[i].e_dist = 0; - pManMR->pDataArray[i].r_dist = 0; - pManMR->pDataArray[i].pred = NULL; - } - } -} diff --git a/src/opt/fret/fretTime.c b/src/opt/fret/fretTime.c deleted file mode 100644 index f497df60..00000000 --- a/src/opt/fret/fretTime.c +++ /dev/null @@ -1,763 +0,0 @@ -/**CFile**************************************************************** - - FileName [fretTime.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Flow-based retiming package.] - - Synopsis [Delay-constrained retiming code.] - - Author [Aaron Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2008.] - - Revision [$Id: fretTime.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "vec.h" -#include "fretime.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ); -static void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ); - -static void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj ); -static void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj ); -static void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk ); -static void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk ); - - -void trace2(Abc_Obj_t *pObj) { - Abc_Obj_t *pNext; - int i; - - print_node(pObj); - Abc_ObjForEachFanin(pObj, pNext, i) - if (pNext->Level >= pObj->Level - 1) { - trace2(pNext); - break; - } -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Initializes timing] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk ) { - - pManMR->nConservConstraints = pManMR->nExactConstraints = 0; - - pManMR->vExactNodes = Vec_PtrAlloc(1000); - - pManMR->vTimeEdges = ALLOC( Vec_Ptr_t, Abc_NtkObjNumMax(pNtk)+1 ); - assert(pManMR->vTimeEdges); - memset(pManMR->vTimeEdges, 0, (Abc_NtkObjNumMax(pNtk)+1) * sizeof(Vec_Ptr_t) ); -} - - -/**Function************************************************************* - - Synopsis [Marks nodes with conservative constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk ) { - Abc_Obj_t *pObj; - int i; - void *pArray; - - // clear all exact constraints - pManMR->nExactConstraints = 0; - while( Vec_PtrSize( pManMR->vExactNodes )) { - pObj = Vec_PtrPop( pManMR->vExactNodes ); - - if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { - pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); - FREE( pArray ); - } - } - -#if !defined(IGNORE_TIMING) - if (pManMR->fIsForward) { - Abc_FlowRetime_ConstrainConserv_forw(pNtk); - } else { - Abc_FlowRetime_ConstrainConserv_back(pNtk); - } -#endif - - Abc_NtkForEachObj( pNtk, pObj, i) - assert( !Vec_PtrSize(FTIMEEDGES(pObj)) ); -} - - -void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk ) { - Vec_Ptr_t *vNodes = pManMR->vNodes; - Abc_Obj_t *pObj, *pNext, *pBi, *pBo; - int i, j; - - assert(!Vec_PtrSize( vNodes )); - pManMR->nConservConstraints = 0; - - // 1. hard constraints - - // (i) collect TFO of PIs - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachPi(pNtk, pObj, i) - Abc_FlowRetime_Dfs_forw( pObj, vNodes ); - - // ... propagate values - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->Level = 0; - Abc_ObjForEachFanin( pObj, pNext, j ) - { - if ( Abc_NodeIsTravIdCurrent(pNext) && - pObj->Level < pNext->Level ) - pObj->Level = pNext->Level; - } - pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; - - if ( Abc_ObjIsBi(pObj) ) - pObj->fMarkA = 1; - - assert(pObj->Level <= pManMR->maxDelay); - } - - // collect TFO of latches - // seed arrival times from BIs - Vec_PtrClear(vNodes); - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachLatch(pNtk, pObj, i) { - pBo = Abc_ObjFanout0( pObj ); - pBi = Abc_ObjFanin0( pObj ); - - Abc_NodeSetTravIdCurrent( pObj ); - Abc_FlowRetime_Dfs_forw( pBo, vNodes ); - - if (pBi->fMarkA) { - pBi->fMarkA = 0; - pObj->Level = pBi->Level; - assert(pObj->Level <= pManMR->maxDelay); - } else - pObj->Level = 0; - } - -#if defined(DEBUG_CHECK) - // DEBUG: check DFS ordering - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->fMarkB = 1; - - Abc_ObjForEachFanin( pObj, pNext, j ) - if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext)) - assert(pNext->fMarkB); - } - Vec_PtrForEachEntryReverse(vNodes, pObj, i) - pObj->fMarkB = 0; -#endif - - // ... propagate values - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->Level = 0; - Abc_ObjForEachFanin( pObj, pNext, j ) - { - if ( Abc_NodeIsTravIdCurrent(pNext) && - pObj->Level < pNext->Level ) - pObj->Level = pNext->Level; - } - pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; - - if (pObj->Level > pManMR->maxDelay) { - FSET(pObj, BLOCK); - } - } - - // 2. conservative constraints - - // first pass: seed latches with T=0 - Abc_NtkForEachLatch(pNtk, pObj, i) { - pObj->Level = 0; - } - - // ... propagate values - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->Level = 0; - Abc_ObjForEachFanin( pObj, pNext, j ) { - if ( Abc_NodeIsTravIdCurrent(pNext) && - pObj->Level < pNext->Level ) - pObj->Level = pNext->Level; - } - pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; - - if ( Abc_ObjIsBi(pObj) ) - pObj->fMarkA = 1; - - assert(pObj->Level <= pManMR->maxDelay); - } - - Abc_NtkForEachLatch(pNtk, pObj, i) { - pBo = Abc_ObjFanout0( pObj ); - pBi = Abc_ObjFanin0( pObj ); - - if (pBi->fMarkA) { - pBi->fMarkA = 0; - pObj->Level = pBi->Level; - assert(pObj->Level <= pManMR->maxDelay); - } else - pObj->Level = 0; - } - - // ... propagate values - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->Level = 0; - Abc_ObjForEachFanin( pObj, pNext, j ) { - if ( Abc_NodeIsTravIdCurrent(pNext) && - pObj->Level < pNext->Level ) - pObj->Level = pNext->Level; - } - pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; - - // constrained? - if (pObj->Level > pManMR->maxDelay) { - FSET( pObj, CONSERVATIVE ); - pManMR->nConservConstraints++; - } else - FUNSET( pObj, CONSERVATIVE ); - } - - Vec_PtrClear( vNodes ); -} - - -void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk ) { - Vec_Ptr_t *vNodes = pManMR->vNodes; - Abc_Obj_t *pObj, *pNext, *pBi, *pBo; - int i, j, l; - - assert(!Vec_PtrSize(vNodes)); - - pManMR->nConservConstraints = 0; - - // 1. hard constraints - - // (i) collect TFO of POs - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachPo(pNtk, pObj, i) - Abc_FlowRetime_Dfs_back( pObj, vNodes ); - - // ... propagate values - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->Level = 0; - Abc_ObjForEachFanout( pObj, pNext, j ) - { - l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); - if ( Abc_NodeIsTravIdCurrent(pNext) && - pObj->Level < l ) - pObj->Level = l; - } - - if ( Abc_ObjIsBo(pObj) ) - pObj->fMarkA = 1; - - assert(pObj->Level <= pManMR->maxDelay); - } - - // collect TFO of latches - // seed arrival times from BIs - Vec_PtrClear(vNodes); - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachLatch(pNtk, pObj, i) { - pBo = Abc_ObjFanout0( pObj ); - pBi = Abc_ObjFanin0( pObj ); - - Abc_NodeSetTravIdCurrent( pObj ); - Abc_FlowRetime_Dfs_back( pBi, vNodes ); - - if (pBo->fMarkA) { - pBo->fMarkA = 0; - pObj->Level = pBo->Level; - assert(pObj->Level <= pManMR->maxDelay); - } else - pObj->Level = 0; - } - -#if defined(DEBUG_CHECK) - // DEBUG: check DFS ordering - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->fMarkB = 1; - - Abc_ObjForEachFanout( pObj, pNext, j ) - if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext)) - assert(pNext->fMarkB); - } - Vec_PtrForEachEntryReverse(vNodes, pObj, i) - pObj->fMarkB = 0; -#endif - - // ... propagate values - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->Level = 0; - Abc_ObjForEachFanout( pObj, pNext, j ) - { - l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); - if ( Abc_NodeIsTravIdCurrent(pNext) && - pObj->Level < l ) - pObj->Level = l; - } - - if (pObj->Level + (Abc_ObjIsNode(pObj)?1:0) > pManMR->maxDelay) { - FSET(pObj, BLOCK); - } - } - - // 2. conservative constraints - - // first pass: seed latches with T=0 - Abc_NtkForEachLatch(pNtk, pObj, i) { - pObj->Level = 0; - } - - // ... propagate values - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->Level = 0; - Abc_ObjForEachFanout( pObj, pNext, j ) { - l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); - if ( Abc_NodeIsTravIdCurrent(pNext) && - pObj->Level < l ) - pObj->Level = l; - } - - if ( Abc_ObjIsBo(pObj) ) { - pObj->fMarkA = 1; - } - - assert(pObj->Level <= pManMR->maxDelay); - } - - Abc_NtkForEachLatch(pNtk, pObj, i) { - pBo = Abc_ObjFanout0( pObj ); - assert(Abc_ObjIsBo(pBo)); - pBi = Abc_ObjFanin0( pObj ); - assert(Abc_ObjIsBi(pBi)); - - if (pBo->fMarkA) { - pBo->fMarkA = 0; - pObj->Level = pBo->Level; - } else - pObj->Level = 0; - } - - // ... propagate values - Vec_PtrForEachEntryReverse(vNodes, pObj, i) { - pObj->Level = 0; - Abc_ObjForEachFanout( pObj, pNext, j ) { - l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); - if ( Abc_NodeIsTravIdCurrent(pNext) && - pObj->Level < l ) - pObj->Level = l; - } - - // constrained? - if (pObj->Level > pManMR->maxDelay) { - FSET( pObj, CONSERVATIVE ); - pManMR->nConservConstraints++; - } else - FUNSET( pObj, CONSERVATIVE ); - } - - Vec_PtrClear( vNodes ); -} - - -/**Function************************************************************* - - Synopsis [Introduces exact timing constraints for a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj ) { - - if (FTEST( pObj, CONSERVATIVE )) { - pManMR->nConservConstraints--; - FUNSET( pObj, CONSERVATIVE ); - } - -#if !defined(IGNORE_TIMING) - if (pManMR->fIsForward) { - Abc_FlowRetime_ConstrainExact_forw(pObj); - } else { - Abc_FlowRetime_ConstrainExact_back(pObj); - } -#endif -} - -void Abc_FlowRetime_ConstrainExact_forw_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) { - Abc_Obj_t *pNext; - int i; - - // terminate? - if (Abc_ObjIsLatch(pObj)) { - if (latch) return; - latch = 1; - } - - // already visited? - if (!latch) { - if (pObj->fMarkA) return; - pObj->fMarkA = 1; - } else { - if (pObj->fMarkB) return; - pObj->fMarkB = 1; - } - - // recurse - Abc_ObjForEachFanin(pObj, pNext, i) { - Abc_FlowRetime_ConstrainExact_forw_rec( pNext, vNodes, latch ); - } - - // add - pObj->Level = 0; - Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch)); -} - -void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj ) { - Vec_Ptr_t *vNodes = pManMR->vNodes; - Abc_Obj_t *pNext, *pCur, *pReg; - // Abc_Ntk_t *pNtk = pManMR->pNtk; - int i, j; - - assert( !Vec_PtrSize(vNodes) ); - assert( !Abc_ObjIsLatch(pObj) ); - assert( !Vec_PtrSize( FTIMEEDGES(pObj) )); - Vec_PtrPush( pManMR->vExactNodes, pObj ); - - // rev topo order - Abc_FlowRetime_ConstrainExact_forw_rec( pObj, vNodes, 0 ); - - Vec_PtrForEachEntryReverse( vNodes, pCur, i) { - pReg = Abc_ObjRegular( pCur ); - - if (pReg == pCur) { - assert(!Abc_ObjIsLatch(pReg)); - Abc_ObjForEachFanin(pReg, pNext, j) - pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); - assert(pReg->Level <= pManMR->maxDelay); - pReg->Level = 0; - pReg->fMarkA = pReg->fMarkB = 0; - } - } - Vec_PtrForEachEntryReverse( vNodes, pCur, i) { - pReg = Abc_ObjRegular( pCur ); - if (pReg != pCur) { - Abc_ObjForEachFanin(pReg, pNext, j) - if (!Abc_ObjIsLatch(pNext)) - pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); - - if (pReg->Level == pManMR->maxDelay) { - Vec_PtrPush( FTIMEEDGES(pObj), pReg); - pManMR->nExactConstraints++; - } - pReg->Level = 0; - pReg->fMarkA = pReg->fMarkB = 0; - } - } - - Vec_PtrClear( vNodes ); -} - -void Abc_FlowRetime_ConstrainExact_back_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) { - Abc_Obj_t *pNext; - int i; - - // terminate? - if (Abc_ObjIsLatch(pObj)) { - if (latch) return; - latch = 1; - } - - // already visited? - if (!latch) { - if (pObj->fMarkA) return; - pObj->fMarkA = 1; - } else { - if (pObj->fMarkB) return; - pObj->fMarkB = 1; - } - - // recurse - Abc_ObjForEachFanout(pObj, pNext, i) { - Abc_FlowRetime_ConstrainExact_back_rec( pNext, vNodes, latch ); - } - - // add - pObj->Level = 0; - Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch)); -} - - -void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj ) { - Vec_Ptr_t *vNodes = pManMR->vNodes; - Abc_Obj_t *pNext, *pCur, *pReg; - // Abc_Ntk_t *pNtk = pManMR->pNtk; - int i, j; - - assert( !Vec_PtrSize( vNodes )); - assert( !Abc_ObjIsLatch(pObj) ); - assert( !Vec_PtrSize( FTIMEEDGES(pObj) )); - Vec_PtrPush( pManMR->vExactNodes, pObj ); - - // rev topo order - Abc_FlowRetime_ConstrainExact_back_rec( pObj, vNodes, 0 ); - - Vec_PtrForEachEntryReverse( vNodes, pCur, i) { - pReg = Abc_ObjRegular( pCur ); - - if (pReg == pCur) { - assert(!Abc_ObjIsLatch(pReg)); - Abc_ObjForEachFanout(pReg, pNext, j) - pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); - assert(pReg->Level <= pManMR->maxDelay); - pReg->Level = 0; - pReg->fMarkA = pReg->fMarkB = 0; - } - } - Vec_PtrForEachEntryReverse( vNodes, pCur, i) { - pReg = Abc_ObjRegular( pCur ); - if (pReg != pCur) { - Abc_ObjForEachFanout(pReg, pNext, j) - if (!Abc_ObjIsLatch(pNext)) - pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); - - if (pReg->Level == pManMR->maxDelay) { - Vec_PtrPush( FTIMEEDGES(pObj), pReg); - pManMR->nExactConstraints++; - } - pReg->Level = 0; - pReg->fMarkA = pReg->fMarkB = 0; - } - } - - Vec_PtrClear( vNodes ); -} - - -/**Function************************************************************* - - Synopsis [Introduces all exact timing constraints in a network] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk ) { - int i; - Abc_Obj_t *pObj; - void *pArray; - - // free existing constraints - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { - pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); - FREE( pArray ); - } - pManMR->nExactConstraints = 0; - - // generate all constraints - Abc_NtkForEachObj(pNtk, pObj, i) - if (!Abc_ObjIsLatch(pObj) && FTEST( pObj, CONSERVATIVE ) && !FTEST( pObj, BLOCK )) - if (!Vec_PtrSize( FTIMEEDGES( pObj ) )) - Abc_FlowRetime_ConstrainExact( pObj ); -} - - - -/**Function************************************************************* - - Synopsis [Deallocates exact constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk ) { - Abc_Obj_t *pObj; - void *pArray; - - while( Vec_PtrSize( pManMR->vExactNodes )) { - pObj = Vec_PtrPop( pManMR->vExactNodes ); - - if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { - pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); - FREE( pArray ); - } - } - - Vec_PtrFree(pManMR->vExactNodes); - FREE( pManMR->vTimeEdges ); -} - - -/**Function************************************************************* - - Synopsis [DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) { - Abc_Obj_t *pNext; - int i; - - if (Abc_ObjIsLatch(pObj)) return; - - Abc_NodeSetTravIdCurrent( pObj ); - - Abc_ObjForEachFanout( pObj, pNext, i ) - if (!Abc_NodeIsTravIdCurrent( pNext )) - Abc_FlowRetime_Dfs_forw( pNext, vNodes ); - - Vec_PtrPush( vNodes, pObj ); -} - - -void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) { - Abc_Obj_t *pNext; - int i; - - if (Abc_ObjIsLatch(pObj)) return; - - Abc_NodeSetTravIdCurrent( pObj ); - - Abc_ObjForEachFanin( pObj, pNext, i ) - if (!Abc_NodeIsTravIdCurrent( pNext )) - Abc_FlowRetime_Dfs_back( pNext, vNodes ); - - Vec_PtrPush( vNodes, pObj ); -} - - -/**Function************************************************************* - - Synopsis [Main timing-constrained routine.] - - Description [Refines constraints that are limiting area improvement. - These are identified by computing - the min-cuts both with and without the conservative - constraints: these two situation represent an - over- and under-constrained version of the timing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_FlowRetime_RefineConstraints( ) { - Abc_Ntk_t *pNtk = pManMR->pNtk; - int i, flow, count = 0; - Abc_Obj_t *pObj; - int maxTighten = 99999; - - vprintf("\t\tsubiter %d : constraints = {cons, exact} = %d, %d\n", - pManMR->subIteration, pManMR->nConservConstraints, pManMR->nExactConstraints); - - // 1. overconstrained - pManMR->constraintMask = BLOCK | CONSERVATIVE; - vprintf("\t\trefinement: over "); - fflush(stdout); - flow = Abc_FlowRetime_PushFlows( pNtk, 0 ); - vprintf("= %d ", flow); - - // remember nodes - if (pManMR->fIsForward) { - Abc_NtkForEachObj( pNtk, pObj, i ) - if (!FTEST(pObj, VISITED_R)) - pObj->fMarkC = 1; - } else { - Abc_NtkForEachObj( pNtk, pObj, i ) - if (!FTEST(pObj, VISITED_E)) - pObj->fMarkC = 1; - } - - if (pManMR->fConservTimingOnly) { - vprintf(" done\n"); - return 0; - } - - // 2. underconstrained - pManMR->constraintMask = BLOCK; - Abc_FlowRetime_ClearFlows( 0 ); - vprintf("under = "); - fflush(stdout); - flow = Abc_FlowRetime_PushFlows( pNtk, 0 ); - vprintf("%d refined nodes = ", flow); - fflush(stdout); - - // find area-limiting constraints - if (pManMR->fIsForward) { - Abc_NtkForEachObj( pNtk, pObj, i ) { - if (pObj->fMarkC && - FTEST(pObj, VISITED_R) && - FTEST(pObj, CONSERVATIVE) && - count < maxTighten) { - count++; - Abc_FlowRetime_ConstrainExact( pObj ); - } - pObj->fMarkC = 0; - } - } else { - Abc_NtkForEachObj( pNtk, pObj, i ) { - if (pObj->fMarkC && - FTEST(pObj, VISITED_E) && - FTEST(pObj, CONSERVATIVE) && - count < maxTighten) { - count++; - Abc_FlowRetime_ConstrainExact( pObj ); - } - pObj->fMarkC = 0; - } - } - - vprintf("%d\n", count); - - return (count > 0); -} - - diff --git a/src/opt/fret/fretime.h b/src/opt/fret/fretime.h deleted file mode 100644 index 167543ce..00000000 --- a/src/opt/fret/fretime.h +++ /dev/null @@ -1,165 +0,0 @@ -/**CFile**************************************************************** - - FileName [fretime.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Flow-based retiming package.] - - Synopsis [Header file for retiming package.] - - Author [Aaron Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2008.] - - Revision [$Id: fretime.h,v 1.00 2008/01/01 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#if !defined(RETIME_H_) -#define RETIME_H_ - -#include "abc.h" - -// #define IGNORE_TIMING -// #define DEBUG_PRINT_FLOWS -// #define DEBUG_VISITED -// #define DEBUG_PREORDER -// #define DEBUG_CHECK - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define MAX_DIST 30000 - -// flags in Flow_Data structure... -#define VISITED_E 0x01 -#define VISITED_R 0x02 -#define VISITED (VISITED_E | VISITED_R) -#define FLOW 0x04 -#define CROSS_BOUNDARY 0x08 -#define BLOCK 0x10 -#define INIT_0 0x20 -#define INIT_1 0x40 -#define INIT_CARE (INIT_0 | INIT_1) -#define CONSERVATIVE 0x80 -#define BLOCK_OR_CONS (BLOCK | CONSERVATIVE) - -typedef struct Flow_Data_t_ { - unsigned int mark : 16; - - union { - Abc_Obj_t *pred; - /* unsigned int var; */ - Abc_Obj_t *pInitObj; - Vec_Ptr_t *vNodes; - }; - - unsigned int e_dist : 16; - unsigned int r_dist : 16; -} Flow_Data_t; - -// useful macros for manipulating Flow_Data structure... -#define FDATA( x ) ((Flow_Data_t *)Abc_ObjCopy(x)) -#define FSET( x, y ) ((Flow_Data_t *)Abc_ObjCopy(x))->mark |= y -#define FUNSET( x, y ) ((Flow_Data_t *)Abc_ObjCopy(x))->mark &= ~y -#define FTEST( x, y ) (((Flow_Data_t *)Abc_ObjCopy(x))->mark & y) -#define FTIMEEDGES( x ) &(pManMR->vTimeEdges[Abc_ObjId( x )]) - -static inline void FSETPRED(Abc_Obj_t *pObj, Abc_Obj_t *pPred) { - assert(!Abc_ObjIsLatch(pObj)); // must preserve field to maintain init state linkage - FDATA(pObj)->pred = pPred; -} -static inline Abc_Obj_t * FGETPRED(Abc_Obj_t *pObj) { - return FDATA(pObj)->pred; -} - - -typedef struct MinRegMan_t_ { - - // problem description: - int maxDelay; - bool fComputeInitState, fGuaranteeInitState; - int nNodes, nLatches; - bool fForwardOnly, fBackwardOnly; - bool fConservTimingOnly; - int nMaxIters; - bool fVerbose; - Abc_Ntk_t *pNtk; - - int nPreRefine; - - // problem state - bool fIsForward; - bool fSinkDistTerminate; - int nExactConstraints, nConservConstraints; - int fSolutionIsDc; - int constraintMask; - int iteration, subIteration; - - // problem data - Vec_Int_t *vSinkDistHist; - Flow_Data_t *pDataArray; - Vec_Ptr_t *vTimeEdges; - Vec_Ptr_t *vExactNodes; - Abc_Ntk_t *pInitNtk; - Vec_Ptr_t *vNodes; // re-useable struct - -} MinRegMan_t ; - -#define vprintf if (pManMR->fVerbose) printf - -/*=== fretMain.c ==========================================================*/ - -extern MinRegMan_t *pManMR; - -Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState, - int fForward, int fBackward, int nMaxIters, - int maxDelay, int fFastButConservative); - -void print_node(Abc_Obj_t *pObj); - -void Abc_ObjBetterTransferFanout( Abc_Obj_t * pFrom, Abc_Obj_t * pTo, int compl ); - -int Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, bool fVerbose ); -bool Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pCur, Abc_Obj_t *pNext ); -void Abc_FlowRetime_ClearFlows( bool fClearAll ); - -/*=== fretFlow.c ==========================================================*/ - -int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ); -int dfsplain_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ); - -void dfsfast_preorder( Abc_Ntk_t *pNtk ); -int dfsfast_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ); -int dfsfast_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ); - -/*=== fretInit.c ==========================================================*/ - -void Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk ); - -void Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk ); - -void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk ); -void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ); - -void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ); -int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ); - -void Abc_FlowRetime_ConstrainInit( ); - -/*=== fretTime.c ==========================================================*/ - -void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk ); -void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk ); - -bool Abc_FlowRetime_RefineConstraints( ); - -void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk ); -void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj ); -void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk ); - -#endif diff --git a/src/opt/fret/module.make b/src/opt/fret/module.make deleted file mode 100644 index fda6a73d..00000000 --- a/src/opt/fret/module.make +++ /dev/null @@ -1,5 +0,0 @@ -SRC += src/opt/fret/fretMain.c \ - src/opt/fret/fretFlow.c \ - src/opt/fret/fretInit.c \ - src/opt/fret/fretTime.c - diff --git a/src/opt/fxu/fxu.c b/src/opt/fxu/fxu.c index d11fd793..46f7ca1a 100644 --- a/src/opt/fxu/fxu.c +++ b/src/opt/fxu/fxu.c @@ -17,6 +17,7 @@ ***********************************************************************/ #include "fxuInt.h" +//#include "mvc.h" #include "fxu.h" //////////////////////////////////////////////////////////////////////// @@ -31,7 +32,7 @@ static int s_MemoryTotal; static int s_MemoryPeak; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -58,7 +59,6 @@ int Fxu_FastExtract( Fxu_Data_t * pData ) Fxu_Single * pSingle; Fxu_Double * pDouble; int Weight1, Weight2, Weight3; - int Counter = 0; s_MemoryTotal = 0; s_MemoryPeak = 0; @@ -78,7 +78,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData ) { Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); if ( pData->fVerbose ) - printf( "Div %5d : Best single = %5d.\r", Counter++, Weight1 ); + printf( "Best single = %3d.\n", Weight1 ); if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 ) Fxu_UpdateSingle( p ); else @@ -93,7 +93,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData ) { Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); if ( pData->fVerbose ) - printf( "Div %5d : Best double = %5d.\r", Counter++, Weight2 ); + printf( "Best double = %3d.\n", Weight2 ); if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 ) Fxu_UpdateDouble( p ); else @@ -110,7 +110,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData ) Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); if ( pData->fVerbose ) - printf( "Div %5d : Best double = %5d. Best single = %5d.\r", Counter++, Weight2, Weight1 ); + printf( "Best double = %3d. Best single = %3d.\n", Weight2, Weight1 ); //Fxu_Select( p, &pSingle, &pDouble ); if ( Weight1 >= Weight2 ) @@ -141,8 +141,8 @@ int Fxu_FastExtract( Fxu_Data_t * pData ) // 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 ); + printf( "Best double = %3d. Best single = %3d. Best complement = %3d.\n", + Weight2, Weight1, Weight3 ); if ( Weight3 > 0 || Weight3 == 0 && pData->fUse0 ) Fxu_Update( p, pSingle, pDouble ); @@ -153,14 +153,13 @@ int Fxu_FastExtract( Fxu_Data_t * pData ) } if ( pData->fVerbose ) - printf( "Total single = %3d. Total double = %3d. Total compl = %3d. \n", - p->nDivs1, p->nDivs2, p->nDivs3 ); + 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 ); +// printf( "Memory usage after delocation: 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; diff --git a/src/opt/fxu/fxu.h b/src/opt/fxu/fxu.h index e6d0b69e..e9f63ea3 100644 --- a/src/opt/fxu/fxu.h +++ b/src/opt/fxu/fxu.h @@ -19,10 +19,6 @@ #ifndef __FXU_H__ #define __FXU_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -37,11 +33,9 @@ extern "C" { /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -#ifndef __cplusplus #ifndef bool #define bool int #endif -#endif typedef struct FxuDataStruct Fxu_Data_t; @@ -55,8 +49,7 @@ struct FxuDataStruct 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 + int nPairsMax; // the maximum number of cube pairs 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 @@ -71,23 +64,19 @@ struct FxuDataStruct }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*===== fxu.c ==========================================================*/ extern int Fxu_FastExtract( Fxu_Data_t * pData ); -#ifdef __cplusplus -} -#endif - -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/opt/fxu/fxuCreate.c b/src/opt/fxu/fxuCreate.c index 55026b27..b061f53d 100644 --- a/src/opt/fxu/fxuCreate.c +++ b/src/opt/fxu/fxuCreate.c @@ -24,16 +24,16 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder ); +static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_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; +static Abc_Fan_t * s_pLits; extern int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -53,7 +53,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) Fxu_Var * pVar; Fxu_Cube * pCubeFirst, * pCubeNew; Fxu_Cube * pCube1, * pCube2; - Vec_Int_t * vFanins; + Vec_Fan_t * vFanins; char * pSopCover; char * pSopCube; int * pOrder, nBitsMax; @@ -69,7 +69,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) nCubesTotal = 0; nPairsTotal = 0; nPairsStore = 0; - nBitsMax = -1; + nBitsMax = -1; for ( i = 0; i < pData->nNodesOld; i++ ) if ( pSopCover = pData->vSops->pArray[i] ) { @@ -89,7 +89,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) return NULL; } - if ( nPairsStore > 50000000 ) + 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; @@ -151,7 +151,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) 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] ] ); + assert( s_pLits[ pOrder[0] ].iFan < s_pLits[ pOrder[nFanins-1] ].iFan ); // create the corresponding cubes in the matrix pCubeFirst = NULL; c = 0; @@ -178,26 +178,11 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) // 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 ); + Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax ); // add the var pairs to the heap - Fxu_MatrixComputeSingles( p, pData->fUse0, pData->nSingleMax ); + Fxu_MatrixComputeSingles( p ); // print stats if ( pData->fVerbose ) @@ -208,8 +193,9 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) 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, "1-cube divisors = %6d. ", p->lSingles.nItems ); + fprintf( stdout, "2-cube divisors = %6d. ", p->nDivsTotal ); + fprintf( stdout, "Cube pairs = %6d.", nPairsTotal ); fprintf( stdout, "\n" ); } // Fxu_MatrixPrint( stdout, p ); @@ -228,7 +214,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) SeeAlso [] ***********************************************************************/ -void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder ) +void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder ) { Fxu_Var * pVar; int Value, i; @@ -238,12 +224,12 @@ void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Value = pSopCube[pOrder[i]]; if ( Value == '0' ) { - pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] + 1 ]; // CST + pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan + 1 ]; // CST Fxu_MatrixAddLiteral( p, pCube, pVar ); } else if ( Value == '1' ) { - pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] ]; // CST + pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan ]; // CST Fxu_MatrixAddLiteral( p, pCube, pVar ); } } @@ -423,7 +409,7 @@ Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iV ***********************************************************************/ int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY ) { - return s_pLits[*ptrX] - s_pLits[*ptrY]; + return s_pLits[*ptrX].iFan - s_pLits[*ptrY].iFan; } //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/fxu/fxuHeapD.c b/src/opt/fxu/fxuHeapD.c index c81ad818..7c123249 100644 --- a/src/opt/fxu/fxuHeapD.c +++ b/src/opt/fxu/fxuHeapD.c @@ -38,7 +38,7 @@ static void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv ); static void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/fxu/fxuHeapS.c b/src/opt/fxu/fxuHeapS.c index eaca8363..dbd66055 100644 --- a/src/opt/fxu/fxuHeapS.c +++ b/src/opt/fxu/fxuHeapS.c @@ -38,7 +38,7 @@ static void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle ); static void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/fxu/fxuInt.h b/src/opt/fxu/fxuInt.h index ea85cb79..59b2df6d 100644 --- a/src/opt/fxu/fxuInt.h +++ b/src/opt/fxu/fxuInt.h @@ -23,6 +23,7 @@ /// INCLUDES /// //////////////////////////////////////////////////////////////////////// +#include "util.h" #include "extra.h" #include "vec.h" @@ -172,8 +173,6 @@ struct FxuMatrix // ~ 30 words // 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; @@ -273,7 +272,7 @@ struct FxuSingle // 7 words }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // minimum/maximum @@ -431,7 +430,7 @@ extern void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p ); #endif //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*===== fxu.c ====================================================*/ @@ -461,7 +460,7 @@ 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_MatrixComputeSingles( Fxu_Matrix * p ); 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 ====================================================*/ @@ -531,9 +530,8 @@ 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 /// //////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/opt/fxu/fxuList.c b/src/opt/fxu/fxuList.c index 52995804..bb081d80 100644 --- a/src/opt/fxu/fxuList.c +++ b/src/opt/fxu/fxuList.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// // matrix -> var diff --git a/src/opt/fxu/fxuMatrix.c b/src/opt/fxu/fxuMatrix.c index 93ec7b90..503ba2f1 100644 --- a/src/opt/fxu/fxuMatrix.c +++ b/src/opt/fxu/fxuMatrix.c @@ -25,7 +25,7 @@ extern unsigned int Cudd_Prime( unsigned int p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -130,7 +130,7 @@ void Fxu_MatrixDelete( Fxu_Matrix * p ) MEM_FREE_FXU( p, Fxu_Var, 1, pVar ); } #else - Extra_MmFixedStop( p->pMemMan ); + Extra_MmFixedStop( p->pMemMan, 0 ); #endif Vec_PtrFree( p->vPairs ); diff --git a/src/opt/fxu/fxuPair.c b/src/opt/fxu/fxuPair.c index 3c031ce8..be6be5e9 100644 --- a/src/opt/fxu/fxuPair.c +++ b/src/opt/fxu/fxuPair.c @@ -55,7 +55,7 @@ static s_Primes[MAX_PRIMES] = }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/fxu/fxuPrint.c b/src/opt/fxu/fxuPrint.c index 232b109a..2d25c0e9 100644 --- a/src/opt/fxu/fxuPrint.c +++ b/src/opt/fxu/fxuPrint.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/fxu/fxuReduce.c b/src/opt/fxu/fxuReduce.c index 0ab8a157..652d807b 100644 --- a/src/opt/fxu/fxuReduce.c +++ b/src/opt/fxu/fxuReduce.c @@ -27,7 +27,7 @@ static int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -90,16 +90,6 @@ int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTota 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; diff --git a/src/opt/fxu/fxuSelect.c b/src/opt/fxu/fxuSelect.c index b9265487..b56407a9 100644 --- a/src/opt/fxu/fxuSelect.c +++ b/src/opt/fxu/fxuSelect.c @@ -37,7 +37,7 @@ void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/fxu/fxuSingle.c b/src/opt/fxu/fxuSingle.c index 73d9a76c..5af5c341 100644 --- a/src/opt/fxu/fxuSingle.c +++ b/src/opt/fxu/fxuSingle.c @@ -17,16 +17,13 @@ ***********************************************************************/ #include "fxuInt.h" -#include "vec.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles ); - //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -41,130 +38,12 @@ static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, SeeAlso [] ***********************************************************************/ -void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax ) +void Fxu_MatrixComputeSingles( Fxu_Matrix * p ) { 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 ); + // iterate through the columns in the matrix 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 ); + Fxu_MatrixComputeSinglesOne( p, pVar ); } /**Function************************************************************* @@ -180,9 +59,12 @@ void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr ***********************************************************************/ void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ) { +// int * pValue2Node = p->pValue2Node; Fxu_Lit * pLitV, * pLitH; Fxu_Var * pVar2; int Coin; +// int CounterAll; +// int CounterTest; int WeightCur; // start collecting the affected vars @@ -194,6 +76,7 @@ void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ) { // get another variable pVar2 = pLitH->pVar; +// CounterAll++; // skip the var if it is already used if ( pVar2->pOrder ) continue; @@ -209,17 +92,16 @@ void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ) // iterate through the selected vars Fxu_MatrixForEachVarInRing( p, pVar2 ) { +// CounterTest++; // 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 ) + if ( WeightCur >= 0 ) Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur ); } + // unmark the vars Fxu_MatrixRingVarsUnmark( p ); } diff --git a/src/opt/fxu/fxuUpdate.c b/src/opt/fxu/fxuUpdate.c index 274f79f6..4006bc76 100644 --- a/src/opt/fxu/fxuUpdate.c +++ b/src/opt/fxu/fxuUpdate.c @@ -37,7 +37,7 @@ static void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p ); static void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -757,14 +757,12 @@ 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 ) @@ -780,7 +778,6 @@ void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p ) } } } -// printf( "Called procedure %d times.\n", Counter ); } /**Function************************************************************* 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 e819a7fb..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 ); - } - - // 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 ); - if ( pPars->nLutSize > 6 ) - pPars->nLutSize = 6; - if ( pPars->nLutSize < 3 ) - pPars->nLutSize = 3; - // 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 facd330b..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 cb448fc0..00000000 --- a/src/opt/res/resCore.c +++ /dev/null @@ -1,419 +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(); - 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); - if ( nFaninsMax > 8 ) - nFaninsMax = 8; - - // 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 ( Abc_ObjFaninNum(pObj) > 8 ) - 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/rwr.h b/src/opt/rwr/rwr.h index f24f9535..6d1a6c06 100644 --- a/src/opt/rwr/rwr.h +++ b/src/opt/rwr/rwr.h @@ -21,10 +21,6 @@ #ifndef __RWR_H__ #define __RWR_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -53,7 +49,6 @@ struct Rwr_Man_t_ 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 @@ -68,17 +63,14 @@ struct Rwr_Man_t_ 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) + 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; @@ -88,8 +80,6 @@ struct Rwr_Man_t_ int timeCut; int timeRes; int timeEval; - int timeMffc; - int timeUpdate; int timeTotal; }; @@ -97,9 +87,6 @@ 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 @@ -111,13 +98,13 @@ struct Rwr_Node_t_ // 24 bytes }; // 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)); } +static inline bool Rwr_IsComplement( Rwr_Node_t * p ) { return (bool)(((unsigned)p) & 01); } +static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned)(p) & ~01); } +static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned)(p) ^ 01); } +static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((unsigned)(p) ^ (c)); } //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -127,9 +114,7 @@ static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_N /*=== 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 ); +extern int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUseZeros ); /*=== rwrLib.c ========================================================*/ extern void Rwr_ManPrecompute( Rwr_Man_t * p ); extern Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute ); @@ -140,12 +125,9 @@ extern void Rwr_ManIncTravId( Rwr_Man_t * p ); 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 ); @@ -157,13 +139,9 @@ 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 /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/opt/rwr/rwrDec.c b/src/opt/rwr/rwrDec.c index ef7af34f..d072879d 100644 --- a/src/opt/rwr/rwrDec.c +++ b/src/opt/rwr/rwrDec.c @@ -29,7 +29,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -49,8 +49,6 @@ void Rwr_ManPreprocess( Rwr_Man_t * p ) 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++ ) { @@ -62,7 +60,6 @@ void Rwr_ManPreprocess( Rwr_Man_t * p ) 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 @@ -135,7 +132,7 @@ Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * eNode1.fCompl = !eNode1.fCompl; // create the decomposition node(s) if ( pNode->fExor ) - eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); + eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1 ); else eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); // save the result diff --git a/src/opt/rwr/rwrEva.c b/src/opt/rwr/rwrEva.c index 396a659c..c934dfd8 100644 --- a/src/opt/rwr/rwrEva.c +++ b/src/opt/rwr/rwrEva.c @@ -25,13 +25,10 @@ /// 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 ); +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 ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -52,35 +49,27 @@ static int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ); SeeAlso [] ***********************************************************************/ -int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ) +int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUseZeros ) { int fVeryVerbose = 0; Dec_Graph_t * pGraph; - Cut_Cut_t * pCut;//, * pTemp; + Cut_Cut_t * pCut; Abc_Obj_t * pFanin; - unsigned uPhase, uTruthBest, uTruth; + unsigned uPhase, uTruthBest; char * pPerm; - int Required, nNodesSaved, nNodesSaveCur; + int Required, nNodesSaved; int i, GainCur, GainBest = -1; - int clk, clk2;//, Counter; + int clk, clk2; p->nNodesConsidered++; // get the required times - Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; - + Required = Abc_NodeReadRequiredLevel( pNode ); // get the node's cuts clk = clock(); - pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); + pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode ); 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 ) @@ -88,12 +77,9 @@ clk = clock(); // 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]; + pPerm = p->pPerms4[ p->pPerms[pCut->uTruth] ]; + uPhase = p->pPhases[pCut->uTruth]; // collect fanins with the corresponding permutation/phase Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); @@ -112,48 +98,29 @@ clk = clock(); } 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 ); + nNodesSaved = Abc_NodeMffcLabel( 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 ); + pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur ); 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); + uTruthBest = pCut->uTruth; // collect fanins in the Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) @@ -164,69 +131,22 @@ 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->nNodesRewritten++; p->nNodesGained += GainBest; - if ( fUseZeros || GainBest > 0 ) - { - p->nNodesRewritten++; - } // report the progress - if ( fVeryVerbose && GainBest > 0 ) + if ( fVeryVerbose ) { 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( "Cone = %2d. ", Dec_GraphNodeNum(p->pGraph) ); + printf( "GAIN = %2d. ", GainBest ); printf( "\n" ); } return GainBest; @@ -243,22 +163,17 @@ p->timeRes += clock() - clk; 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 ) +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 ) { - extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); 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] ); + vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[pCut->uTruth] ); p->nSubgraphs += vSubgraphs->nSize; // determine the best subgraph GainBest = -1; - CostBest = ABC_INFINITY; Vec_PtrForEachEntry( vSubgraphs, pNode, i ) { // get the current graph @@ -271,58 +186,11 @@ Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCu 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 ) { - // 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; - } - } + GainBest = nNodesSaved - nNodesAdded; + pGraphBest = pGraphCur; } } if ( GainBest == -1 ) @@ -331,257 +199,6 @@ Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCu 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 index 2d00bb1c..e93a2611 100644 --- a/src/opt/rwr/rwrExp.c +++ b/src/opt/rwr/rwrExp.c @@ -47,7 +47,7 @@ static Rwr_Man4_t * s_pManRwrExp4 = NULL; static Rwr_Man5_t * s_pManRwrExp5 = NULL; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/rwr/rwrLib.c b/src/opt/rwr/rwrLib.c index 1cdf350e..fbcb8916 100644 --- a/src/opt/rwr/rwrLib.c +++ b/src/opt/rwr/rwrLib.c @@ -28,7 +28,7 @@ static Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_N static void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/rwr/rwrMan.c b/src/opt/rwr/rwrMan.c index 87a080c7..a21dd520 100644 --- a/src/opt/rwr/rwrMan.c +++ b/src/opt/rwr/rwrMan.c @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -50,7 +50,7 @@ clk = clock(); p = ALLOC( Rwr_Man_t, 1 ); memset( p, 0, sizeof(Rwr_Man_t) ); p->nFuncs = (1<<16); - pManDec = Abc_FrameReadManDec(); + pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame()); p->puCanons = pManDec->puCanons; p->pPhases = pManDec->pPhases; p->pPerms = pManDec->pPerms; @@ -75,7 +75,6 @@ clk = clock(); 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 ); @@ -113,13 +112,11 @@ void Rwr_ManStop( Rwr_Man_t * p ) 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 ); + Extra_MmFixedStop( p->pMmNode, 0 ); free( p->pTable ); free( p->pPractical ); free( p->pPerms4 ); @@ -150,50 +147,20 @@ void Rwr_ManPrintStats( Rwr_Man_t * p ) 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 ); + printf( "Calculated gain = %8d.\n", p->nNodesGained ); 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" ); + printf( "The scores are : " ); 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( "%d=%d ", i, p->nScores[i] ); 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************************************************************* @@ -212,22 +179,6 @@ 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.] @@ -260,22 +211,6 @@ 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.] diff --git a/src/opt/rwr/rwrPrint.c b/src/opt/rwr/rwrPrint.c index 82ad2a90..30c99f00 100644 --- a/src/opt/rwr/rwrPrint.c +++ b/src/opt/rwr/rwrPrint.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -77,33 +77,6 @@ void Rwr_GetBushVolume( Rwr_Man_t * p, int Entry, int * pVolume, int * pnFuncs ) *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.] @@ -246,9 +219,9 @@ void Rwr_ManPrint( Rwr_Man_t * p ) continue; if ( i != p->puCanons[i] ) continue; - fprintf( pFile, "\nClass %3d. Func %6d. ", p->pMap[i], Counter++ ); + 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) ); + fprintf( pFile, "Functions = %2d. Volume = %2d. ", nFuncs, Volume ); uTruth = i; Extra_PrintBinary( pFile, &uTruth, 16 ); fprintf( pFile, "\n" ); 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 index b2add2bf..65b2bd6f 100644 --- a/src/opt/rwr/rwrUtil.c +++ b/src/opt/rwr/rwrUtil.c @@ -34,7 +34,7 @@ static unsigned short s_RwtAigSubgraphs[]; #endif //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/opt/sim/module.make b/src/opt/sim/module.make index 54058402..43d0a125 100644 --- a/src/opt/sim/module.make +++ b/src/opt/sim/module.make @@ -1,6 +1,5 @@ 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 \ diff --git a/src/opt/sim/sim.h b/src/opt/sim/sim.h index 7fcf5ae6..afed7190 100644 --- a/src/opt/sim/sim.h +++ b/src/opt/sim/sim.h @@ -17,14 +17,10 @@ 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, @@ -102,7 +98,6 @@ struct Sim_Man_t_ 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 @@ -140,11 +135,11 @@ struct Sim_Pat_t_ }; //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// -#define SIM_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) -#define SIM_LAST_BITS(n) ((((n)&31) > 0)? (n)&31 : 32) +#define SIM_NUM_WORDS(n) ((n)/32 + (((n)%32) > 0)) +#define SIM_LAST_BITS(n) ((((n)%32) > 0)? (n)%32 : 32) #define SIM_MASK_FULL (0xFFFFFFFF) #define SIM_MASK_BEG(n) (SIM_MASK_FULL >> (32-n)) @@ -167,7 +162,6 @@ struct Sim_Pat_t_ #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 /// @@ -177,14 +171,11 @@ struct Sim_Pat_t_ 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 Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk ); 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 ); @@ -206,28 +197,17 @@ 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 void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ); 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 void Sim_UtilGetRandom( unsigned * pPatRand, 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 /// //////////////////////////////////////////////////////////////////////// +#endif + diff --git a/src/opt/sim/simMan.c b/src/opt/sim/simMan.c index 3b50ad84..780ecfd8 100644 --- a/src/opt/sim/simMan.c +++ b/src/opt/sim/simMan.c @@ -26,12 +26,12 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Starts the simulation manager.] + Synopsis [Starts the simulatin manager.] Description [] @@ -83,7 +83,7 @@ Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose ) /**Function************************************************************* - Synopsis [Stops the simulation manager.] + Synopsis [Stops the simulatin manager.] Description [] @@ -149,9 +149,11 @@ void Sym_ManPrintStats( Sym_Man_t * p ) } + + /**Function************************************************************* - Synopsis [Starts the simulation manager.] + Synopsis [Starts the simulatin manager.] Description [] @@ -160,7 +162,7 @@ void Sym_ManPrintStats( Sym_Man_t * p ) SeeAlso [] ***********************************************************************/ -Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight ) +Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk ) { Sim_Man_t * p; // start the manager @@ -173,27 +175,24 @@ Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight ) 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 ); - } + 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.] + Synopsis [Stops the simulatin manager.] Description [] @@ -210,7 +209,7 @@ void Sim_ManStop( Sim_Man_t * p ) 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->pMmPat ) Extra_MmFixedStop( p->pMmPat, 0 ); if ( p->vFifo ) Vec_PtrFree( p->vFifo ); if ( p->vDiffs ) Vec_IntFree( p->vDiffs ); free( p ); diff --git a/src/opt/sim/simSat.c b/src/opt/sim/simSat.c index d514f7f2..b4e080fe 100644 --- a/src/opt/sim/simSat.c +++ b/src/opt/sim/simSat.c @@ -26,7 +26,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* 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 index f7048f4a..576e19cc 100644 --- a/src/opt/sim/simSupp.c +++ b/src/opt/sim/simSupp.c @@ -35,8 +35,10 @@ 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 ); +extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes ); + //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -66,8 +68,8 @@ Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk ) // derive the structural supports of the internal nodes Abc_NtkForEachNode( pNtk, pNode, i ) { -// if ( Abc_NodeIsConst(pNode) ) -// continue; + if ( Abc_NodeIsConst(pNode) ) + continue; pSimmNode = vSuppStr->pArray[ pNode->Id ]; pSimmNode1 = vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ]; pSimmNode2 = vSuppStr->pArray[ Abc_ObjFaninId1(pNode) ]; @@ -106,7 +108,7 @@ Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ) srand( 0xABC ); // start the simulation manager - p = Sim_ManStart( pNtk, 0 ); + p = Sim_ManStart( pNtk ); // compute functional support using one round of random simulation Sim_UtilAssignRandom( p ); @@ -467,10 +469,9 @@ void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int Limit ) // 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 ); + pMan = Abc_NtkToFraig( pMiter, &Params, 0 ); p->timeFraig += clock() - clk; clk = clock(); Fraig_ManProveMiter( pMan ); @@ -586,6 +587,10 @@ int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Out } // perform the traversal RetValue = 3 & Sim_NtkSimTwoPats_rec( Abc_ObjFanin0( Abc_NtkCo(pNtk,Output) ) ); + if ( RetValue == 0 || RetValue == 3 ) + { + int x = 0; + } // assert( RetValue == 1 || RetValue == 2 ); return RetValue == 1 || RetValue == 2; } diff --git a/src/opt/sim/simSwitch.c b/src/opt/sim/simSwitch.c index 218d4d59..b43597f3 100644 --- a/src/opt/sim/simSwitch.c +++ b/src/opt/sim/simSwitch.c @@ -29,7 +29,7 @@ static void Sim_NodeSimulate( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimW static float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -65,7 +65,7 @@ Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ) Abc_NtkForEachCi( pNtk, pNode, i ) { pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id); - Sim_UtilSetRandom( pSimInfo, nSimWords ); + Sim_UtilGetRandom( pSimInfo, nSimWords ); pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords ); } // simulate the internal nodes @@ -73,7 +73,7 @@ Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ) Vec_PtrForEachEntry( vNodes, pNode, i ) { pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id); - Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords, 0 ); + Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords ); pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords ); } Vec_PtrFree( vNodes ); diff --git a/src/opt/sim/simSym.c b/src/opt/sim/simSym.c index 71de5b05..c452bb1b 100644 --- a/src/opt/sim/simSym.c +++ b/src/opt/sim/simSym.c @@ -26,7 +26,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -71,7 +71,7 @@ p->timeStruct = clock() - clk; for ( i = 1; i <= 1000; i++ ) { // simulate this pattern - Sim_UtilSetRandom( p->uPatRand, p->nSimWords ); + Sim_UtilGetRandom( p->uPatRand, p->nSimWords ); Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); if ( i % 50 != 0 ) continue; @@ -125,7 +125,6 @@ p->timeStruct = clock() - clk; 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; diff --git a/src/opt/sim/simSymSat.c b/src/opt/sim/simSymSat.c index 7690a891..db9917b3 100644 --- a/src/opt/sim/simSymSat.c +++ b/src/opt/sim/simSymSat.c @@ -26,10 +26,11 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern ); +extern int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern ); +extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -144,10 +145,9 @@ int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * Params.fInternal = 1; Params.nPatsRand = 512; Params.nPatsDyna = 512; - Params.nSeconds = ABC_INFINITY; clk = clock(); - pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 ); + pMan = Abc_NtkToFraig( pMiter, &Params, 0 ); p->timeFraig += clock() - clk; clk = clock(); Fraig_ManProveMiter( pMan ); diff --git a/src/opt/sim/simSymSim.c b/src/opt/sim/simSymSim.c index 2282825b..94028c47 100644 --- a/src/opt/sim/simSymSim.c +++ b/src/opt/sim/simSymSim.c @@ -29,7 +29,7 @@ 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -55,9 +55,9 @@ void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPat, Vec_Ptr_t * vMatrsNonSym clk = clock(); Vec_PtrForEachEntry( p->vNodes, pNode, i ) { -// if ( Abc_NodeIsConst(pNode) ) -// continue; - Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords, 0 ); + if ( Abc_NodeIsConst(pNode) ) + continue; + Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords ); } p->timeSim += clock() - clk; // collect info into the CO matrices @@ -65,8 +65,8 @@ clk = clock(); Abc_NtkForEachCo( p->pNtk, pNode, i ) { pNode = Abc_ObjFanin0(pNode); -// if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) -// continue; + if ( Abc_ObjIsCi(pNode) || Abc_NodeIsConst(pNode) ) + continue; nPairsTotal = Vec_IntEntry(p->vPairsTotal, i); nPairsSym = Vec_IntEntry(p->vPairsSym, i); nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i); diff --git a/src/opt/sim/simSymStr.c b/src/opt/sim/simSymStr.c index d52c4328..ed7e93bf 100644 --- a/src/opt/sim/simSymStr.c +++ b/src/opt/sim/simSymStr.c @@ -41,7 +41,7 @@ static void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * v static int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -74,16 +74,15 @@ void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * v vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( vNodes, pTemp, i ) { -// if ( Abc_NodeIsConst(pTemp) ) -// continue; + 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) ) + if ( Abc_ObjIsCi(pTemp) || Abc_NodeIsConst(pTemp) ) continue; Sim_SymmsTransferToMatrix( Vec_PtrEntry(vMatrs, i), SIM_READ_SYMMS(pTemp), Vec_PtrEntry(vSuppFun, i) ); } @@ -93,7 +92,7 @@ void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * v Abc_NtkForEachCi( pNtk, pTemp, i ) Vec_IntFree( SIM_READ_SYMMS(pTemp) ); Vec_PtrForEachEntry( vNodes, pTemp, i ) -// if ( !Abc_NodeIsConst(pTemp) ) + if ( !Abc_NodeIsConst(pTemp) ) Vec_IntFree( SIM_READ_SYMMS(pTemp) ); Vec_PtrFree( vNodes ); free( pMap ); @@ -445,7 +444,6 @@ void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, u 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) ) diff --git a/src/opt/sim/simUtils.c b/src/opt/sim/simUtils.c index b0660001..4b89c650 100644 --- a/src/opt/sim/simUtils.c +++ b/src/opt/sim/simUtils.c @@ -37,7 +37,7 @@ static int bit_count[256] = { }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -232,6 +232,9 @@ void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fT // simulate the internal nodes if ( Abc_ObjIsNode(pNode) ) { + if ( Abc_NodeIsConst(pNode) ) + return; + if ( fType ) pSimmNode = p->vSim1->pArray[ pNode->Id ]; else @@ -296,18 +299,17 @@ void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fT SeeAlso [] ***********************************************************************/ -void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset ) +void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) { unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; int k, fComp1, fComp2; // simulate the internal nodes assert( Abc_ObjIsNode(pNode) ); + if ( Abc_NodeIsConst(pNode) ) + return; 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 ) @@ -324,36 +326,6 @@ void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimW 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.] @@ -408,31 +380,10 @@ int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords ) 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.] + Synopsis [Returns the random pattern.] Description [] @@ -441,111 +392,13 @@ Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords ) SeeAlso [] ***********************************************************************/ -void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords ) +void Sim_UtilGetRandom( 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.] @@ -596,51 +449,6 @@ int Sim_UtilCountPairsOne( Extra_BitMat_t * pMat, Vec_Int_t * vSupport ) 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.] 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/asat/added.c b/src/sat/asat/added.c new file mode 100644 index 00000000..d7f5b104 --- /dev/null +++ b/src/sat/asat/added.c @@ -0,0 +1,126 @@ +/**CFile**************************************************************** + + FileName [added.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: added.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include "solver.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 inline int lit_var(lit l) { return l >> 1; } +static inline int lit_sign(lit l) { return (l & 1); } + +static void Asat_ClauseWriteDimacs( FILE * pFile, clause * pC, bool fIncrement ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the clauses in the solver into a file in DIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_SolverWriteDimacs( solver * p, char * pFileName ) +{ + 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" ); + 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++ ) + Asat_ClauseWriteDimacs( pFile, pClauses[i], 1 ); + + // write the learned clauses + nClauses = p->learnts.size; + pClauses = p->learnts.ptr; + for ( i = 0; i < nClauses; i++ ) + Asat_ClauseWriteDimacs( pFile, pClauses[i], 1 ); + + // 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 0\n", (p->assigns[i] == l_False)? "-": "", i + 1 ); + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes the given clause in a file in DIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_ClauseWriteDimacs( 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" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/sat/asat/main.c b/src/sat/asat/main.c new file mode 100644 index 00000000..cbad5ba1 --- /dev/null +++ b/src/sat/asat/main.c @@ -0,0 +1,195 @@ +/************************************************************************************************** +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 "solver.h" + +#include +#include +#include +//#include +//#include +//#include +//#include +//#include + +//================================================================================================= +// Helpers: + + +// Reads an input stream to end-of-file and returns the result as a 'char*' terminated by '\0' +// (dynamic allocation in case 'in' is standard input). +// +char* readFile(FILE * in) +{ + char* data = malloc(65536); + int cap = 65536; + int size = 0; + + while (!feof(in)){ + if (size == cap){ + cap *= 2; + data = realloc(data, cap); } + size += fread(&data[size], 1, 65536, in); + } + data = realloc(data, size+1); + data[size] = '\0'; + + return data; +} + +//static inline double cpuTime(void) { +// struct rusage ru; +// getrusage(RUSAGE_SELF, &ru); +// return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } + + +//================================================================================================= +// DIMACS Parser: + + +static inline void skipWhitespace(char** in) { + while ((**in >= 9 && **in <= 13) || **in == 32) + (*in)++; } + +static inline void skipLine(char** in) { + for (;;){ + if (**in == 0) return; + if (**in == '\n') { (*in)++; return; } + (*in)++; } } + +static inline int parseInt(char** in) { + int val = 0; + int _neg = 0; + skipWhitespace(in); + if (**in == '-') _neg = 1, (*in)++; + else if (**in == '+') (*in)++; + if (**in < '0' || **in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", **in), exit(1); + while (**in >= '0' && **in <= '9') + val = val*10 + (**in - '0'), + (*in)++; + return _neg ? -val : val; } + +static void readClause(char** in, solver* s, vec* lits) { + int parsed_lit, var; + vec_resize(lits,0); + for (;;){ + parsed_lit = parseInt(in); + if (parsed_lit == 0) break; + var = abs(parsed_lit)-1; + vec_push(lits, (void*)(parsed_lit > 0 ? toLit(var) : neg(toLit(var)))); + } +} + +static lbool parse_DIMACS_main(char* in, solver* s) { + vec lits; + vec_new(&lits); + + for (;;){ + skipWhitespace(&in); + if (*in == 0) + break; + else if (*in == 'c' || *in == 'p') + skipLine(&in); + else{ + lit* begin; + readClause(&in, s, &lits); + begin = (lit*)vec_begin(&lits); + if (solver_addclause(s, begin, begin+vec_size(&lits)) == l_False){ + vec_delete(&lits); + return l_False; + } + } + } + vec_delete(&lits); + return solver_simplify(s); +} + + +// Inserts problem into solver. Returns FALSE upon immediate conflict. +// +static lbool parse_DIMACS(FILE * in, solver* s) { + char* text = readFile(in); + lbool ret = parse_DIMACS_main(text, s); + free(text); + return ret; } + + +//================================================================================================= + + +void printStats(stats* stats, int cpu_time) +{ + double Time = (float)(cpu_time)/(float)(CLOCKS_PER_SEC); + printf("restarts : %12d\n", stats->starts); + printf("conflicts : %12.0f (%9.0f / sec )\n", (double)stats->conflicts , (double)stats->conflicts /Time); + printf("decisions : %12.0f (%9.0f / sec )\n", (double)stats->decisions , (double)stats->decisions /Time); + printf("propagations : %12.0f (%9.0f / sec )\n", (double)stats->propagations, (double)stats->propagations/Time); + printf("inspects : %12.0f (%9.0f / sec )\n", (double)stats->inspects , (double)stats->inspects /Time); + printf("conflict literals : %12.0f (%9.2f %% deleted )\n", (double)stats->tot_literals, (double)(stats->max_literals - stats->tot_literals) * 100.0 / (double)stats->max_literals); + printf("CPU time : %12.2f sec\n", Time); +} + +//solver* slv; +//static void SIGINT_handler(int signum) { +// printf("\n"); printf("*** INTERRUPTED ***\n"); +// printStats(&slv->stats, cpuTime()); +// printf("\n"); printf("*** INTERRUPTED ***\n"); +// exit(0); } + + +//================================================================================================= + + +int main(int argc, char** argv) +{ + solver* s = solver_new(); + lbool st; + FILE * in; + int clk = clock(); + + if (argc != 2) + fprintf(stderr, "ERROR! Not enough command line arguments.\n"), + exit(1); + + in = fopen(argv[1], "rb"); + if (in == NULL) + fprintf(stderr, "ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), + exit(1); + st = parse_DIMACS(in, s); + fclose(in); + + if (st == l_False){ + solver_delete(s); + printf("Trivial problem\nUNSATISFIABLE\n"); + exit(20); + } + + s->verbosity = 1; +// slv = s; +// signal(SIGINT,SIGINT_handler); + st = solver_solve(s,0,0); + printStats(&s->stats, clock() - clk); + printf("\n"); + printf(st == l_True ? "SATISFIABLE\n" : "UNSATISFIABLE\n"); + + solver_delete(s); + return 0; +} diff --git a/src/sat/asat/module.make b/src/sat/asat/module.make new file mode 100644 index 00000000..882176fa --- /dev/null +++ b/src/sat/asat/module.make @@ -0,0 +1,2 @@ +SRC += src/sat/asat/added.c \ + src/sat/asat/solver.c diff --git a/src/sat/asat/solver.c b/src/sat/asat/solver.c new file mode 100644 index 00000000..c9dadcb4 --- /dev/null +++ b/src/sat/asat/solver.c @@ -0,0 +1,1167 @@ +/************************************************************************************************** +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 "solver.h" + +//================================================================================================= +// Simple (var/literal) helpers: + +static inline int lit_var(lit l) { return l >> 1; } +static inline int lit_sign(lit l) { return (l & 1); } + +//================================================================================================= +// Debug: + +//#define VERBOSEDEBUG + +// For derivation output (verbosity level 2) +#define L_IND "%-*d" +#define L_ind solver_dlevel(s)*3+3,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: + +void 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: + +clause* clause_from_lit (lit l) { return (clause*)(l + l + 1); } +bool clause_is_lit (clause* c) { return ((unsigned int)c & 1); } +lit clause_read_lit (clause* c) { return (lit)((unsigned int)c >> 1); } + +//================================================================================================= +// Simple helpers: + +static inline int solver_dlevel(solver* s) { return vec_size(&s->trail_lim); } +static inline vec* solver_read_wlist (solver* s, lit l){ return &s->wlists[l]; } +static inline void vec_remove(vec* v, void* e) +{ + void** ws = vec_begin(v); + int j = 0; + + for (; ws[j] != e ; j++); + assert(j < vec_size(v)); + for (; j < vec_size(v)-1; j++) ws[j] = ws[j+1]; + vec_resize(v,vec_size(v)-1); +} + +//================================================================================================= +// Variable order functions: + +static inline void order_update(solver* s, int v) // updateorder +{ + int* orderpos = s->orderpos; + double* activity = s->activity; + int* heap = (int*)vec_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(solver* s, int v) +{ +} + +static inline void order_unassigned(solver* s, int v) // undoorder +{ + int* orderpos = s->orderpos; + if (orderpos[v] == -1){ + orderpos[v] = vec_size(&s->order); + vec_push(&s->order,(void*)v); + order_update(s,v); + } +} + +static int order_select(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 = (int*)vec_begin(&s->order); + activity = s->activity; + orderpos = s->orderpos; + + + while (vec_size(&s->order) > 0){ + int next = heap[0]; + int size = vec_size(&s->order)-1; + int x = heap[size]; + + vec_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; + } + + if (values[next] == l_Undef) + return next; + } + + return var_Undef; +} + +//================================================================================================= +// Activity functions: + +static inline void act_var_rescale(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(solver* s, int v) { + double* activity = s->activity; + if ((activity[v] += s->var_inc) > 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(solver* s) { s->var_inc *= s->var_decay; } + +static inline void act_clause_rescale(solver* s) { + clause** cs = (clause**)vec_begin(&s->learnts); + int i; + for (i = 0; i < vec_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(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(solver* s) { s->cla_inc *= s->cla_decay; } + + +//================================================================================================= +// Clause functions: + +/* pre: size > 1 && no variable occurs twice + */ +static clause* clause_new(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)); + 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(neg(begin[0]) < s->size*2); + assert(neg(begin[1]) < s->size*2); + + //vec_push(solver_read_wlist(s,neg(begin[0])),(void*)c); + //vec_push(solver_read_wlist(s,neg(begin[1])),(void*)c); + + vec_push(solver_read_wlist(s,neg(begin[0])),(void*)(size > 2 ? c : clause_from_lit(begin[1]))); + vec_push(solver_read_wlist(s,neg(begin[1])),(void*)(size > 2 ? c : clause_from_lit(begin[0]))); + + return c; +} + + +static void clause_remove(solver* s, clause* c) +{ + lit* lits = clause_begin(c); + assert(neg(lits[0]) < s->size*2); + assert(neg(lits[1]) < s->size*2); + + //vec_remove(solver_read_wlist(s,neg(lits[0])),(void*)c); + //vec_remove(solver_read_wlist(s,neg(lits[1])),(void*)c); + + assert(lits[0] < s->size*2); + vec_remove(solver_read_wlist(s,neg(lits[0])),(void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[1]))); + vec_remove(solver_read_wlist(s,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); + } + + free(c); +} + + +static lbool clause_simplify(solver* s, clause* c) +{ + lit* lits = clause_begin(c); + lbool* values = s->assigns; + int i; + + assert(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: + +static void solver_setnvars(solver* s,int n) +{ + int var; + if (s->cap < n){ + + while (s->cap < n) s->cap = s->cap*2+1; + + s->wlists = (vec*) realloc(s->wlists, sizeof(vec)*s->cap*2); + s->activity = (double*) realloc(s->activity, 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++){ + vec_new(&s->wlists[2*var]); + vec_new(&s->wlists[2*var+1]); + s->activity [var] = 0; + s->assigns [var] = l_Undef; + s->orderpos [var] = var; + s->reasons [var] = (clause*)0; + s->levels [var] = 0; + s->tags [var] = l_Undef; + + assert(vec_size(&s->order) == var); + vec_push(&s->order,(void*)var); + order_update(s,var); + } + + s->size = n > s->size ? n : s->size; +} + + +static inline bool enqueue(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] = solver_dlevel(s); + reasons[v] = from; + s->trail[s->qtail++] = l; + + order_assigned(s, v); + return true; + } +} + + +static inline void assume(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 + vec_push(&s->trail_lim,(void*)s->qtail); + enqueue(s,l,(clause*)0); +} + + +static inline void solver_canceluntil(solver* s, int level) { + lit* trail; + lbool* values; + clause** reasons; + int bound; + int c; + + if (solver_dlevel(s) <= level) + return; + + trail = s->trail; + values = s->assigns; + reasons = s->reasons; + bound = ((int*)vec_begin(&s->trail_lim))[level]; + + 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; + vec_resize(&s->trail_lim,level); +} + +static void solver_record(solver* s, vec* cls) +{ + lit* begin = (lit*)vec_begin(cls); + lit* end = begin + vec_size(cls); + clause* c = (vec_size(cls) > 1) ? clause_new(s,begin,end,1) : (clause*)0; + enqueue(s,*begin,c); + + assert(vec_size(cls) > 0); + + if (c != 0) { + vec_push(&s->learnts,(void*)c); + act_clause_bump(s,c); + s->stats.learnts++; + s->stats.learnts_literals += vec_size(cls); + } +} + + +static double solver_progress(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 solver_lit_removable(solver* s, lit l, int minl) +{ + lbool* tags = s->tags; + clause** reasons = s->reasons; + int* levels = s->levels; + int top = vec_size(&s->tagged); + + assert(lit_var(l) >= 0 && lit_var(l) < s->size); + assert(reasons[lit_var(l)] != 0); + vec_resize(&s->stack,0); + vec_push(&s->stack,(void*)lit_var(l)); + + while (vec_size(&s->stack) > 0){ + clause* c; + int v = (int)vec_begin(&s->stack)[vec_size(&s->stack)-1]; + assert(v >= 0 && v < s->size); + vec_resize(&s->stack,vec_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)){ + vec_push(&s->stack,(void*)v); + tags[v] = l_True; + vec_push(&s->tagged,(void*)v); + }else{ + int* tagged = (int*)vec_begin(&s->tagged); + int j; + for (j = top; j < vec_size(&s->tagged); j++) + tags[tagged[j]] = l_Undef; + vec_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)){ + + vec_push(&s->stack,(void*)lit_var(lits[i])); + tags[v] = l_True; + vec_push(&s->tagged,(void*)v); + }else{ + int* tagged = (int*)vec_begin(&s->tagged); + for (j = top; j < vec_size(&s->tagged); j++) + tags[tagged[j]] = l_Undef; + vec_resize(&s->tagged,top); + return false; + } + } + } + } + } + + return true; +} + +static void solver_analyze(solver* s, clause* c, vec* 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; + + vec_push(learnt,(void*)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; + vec_push(&s->tagged,(void*)lit_var(q)); + act_var_bump(s,lit_var(q)); + if (levels[lit_var(q)] == solver_dlevel(s)) + cnt++; + else + vec_push(learnt,(void*)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; + vec_push(&s->tagged,(void*)lit_var(q)); + act_var_bump(s,lit_var(q)); + if (levels[lit_var(q)] == solver_dlevel(s)) + cnt++; + else + vec_push(learnt,(void*)q); + } + } + } + + while (tags[lit_var(trail[ind--])] == l_Undef); + + p = trail[ind+1]; + c = reasons[lit_var(p)]; + cnt--; + + }while (cnt > 0); + + *(lit*)vec_begin(learnt) = neg(p); + + lits = (lit*)vec_begin(learnt); + minl = 0; + for (i = 1; i < vec_size(learnt); i++){ + int lev = levels[lit_var(lits[i])]; + minl |= 1 << (lev & 31); + } + + // simplify (full) + for (i = j = 1; i < vec_size(learnt); i++){ + if (reasons[lit_var(lits[i])] == 0 || !solver_lit_removable(s,lits[i],minl)) + lits[j++] = lits[i]; + } + + // update size of learnt + statistics + s->stats.max_literals += vec_size(learnt); + vec_resize(learnt,j); + s->stats.tot_literals += j; + + // clear tags + tagged = (int*)vec_begin(&s->tagged); + for (i = 0; i < vec_size(&s->tagged); i++) + tags[tagged[i]] = l_Undef; + vec_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 < vec_size(learnt); i++) printf(" "L_LIT, L_lit(lits[i])); +#endif + if (vec_size(learnt) > 1){ + int max_i = 1; + int max = levels[lit_var(lits[1])]; + lit tmp; + + for (i = 2; i < vec_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 = vec_size(learnt) > 1 ? levels[lit_var(lits[1])] : 0; + printf(" } at level %d\n", lev); + } +#endif +} + + +clause* solver_propagate(solver* s) +{ + lbool* values = s->assigns; + clause* confl = (clause*)0; + lit* lits; + + //printf("solver_propagate\n"); + while (confl == 0 && s->qtail - s->qhead > 0){ + lit p = s->trail[s->qhead++]; + vec* ws = solver_read_wlist(s,p); + clause **begin = (clause**)vec_begin(ws); + clause **end = begin + vec_size(ws); + clause **i, **j; + + s->stats.propagations++; + s->simpdb_props--; + + //printf("checking lit %d: "L_LIT"\n", vec_size(ws), L_lit(p)); + for (i = j = begin; i < end; ){ + if (clause_is_lit(*i)){ + *j++ = *i; + if (!enqueue(s,clause_read_lit(*i),clause_from_lit(p))){ + confl = s->binary; + (clause_begin(confl))[1] = neg(p); + (clause_begin(confl))[0] = clause_read_lit(*i++); + + // Copy the remaining watches: + 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 = 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; + vec_push(solver_read_wlist(s,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: + while (i < end) + *j++ = *i++; + } + } + } + next: + i++; + } + + s->stats.inspects += j - (clause**)vec_begin(ws); + vec_resize(ws,j - (clause**)vec_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 solver_reducedb(solver* s) +{ + int i, j; + double extra_lim = s->cla_inc / vec_size(&s->learnts); // Remove any clause below this activity + clause** learnts = (clause**)vec_begin(&s->learnts); + clause** reasons = s->reasons; + + sort(vec_begin(&s->learnts), vec_size(&s->learnts), &clause_cmp); + + for (i = j = 0; i < vec_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 < vec_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", vec_size(&s->learnts) - j); + + + vec_resize(&s->learnts,j); +} + +static lbool solver_search(solver* s, int nof_conflicts, int nof_learnts) +{ + int* levels = s->levels; + double var_decay = 0.95; + double clause_decay = 0.999; + double random_var_freq = 0.02; + + int conflictC = 0; + vec learnt_clause; + + assert(s->root_level == solver_dlevel(s)); + + s->stats.starts++; + s->var_decay = (float)(1 / var_decay ); + s->cla_decay = (float)(1 / clause_decay); + vec_resize(&s->model,0); + vec_new(&learnt_clause); + + for (;;){ + clause* confl = solver_propagate(s); + if (confl != 0){ + // CONFLICT + int blevel; + +#ifdef VERBOSEDEBUG + printf(L_IND"**CONFLICT**\n", L_ind); +#endif + s->stats.conflicts++; conflictC++; + if (solver_dlevel(s) == s->root_level){ + vec_delete(&learnt_clause); + return l_False; + } + + vec_resize(&learnt_clause,0); + solver_analyze(s, confl, &learnt_clause); + blevel = vec_size(&learnt_clause) > 1 ? levels[lit_var(((lit*)vec_begin(&learnt_clause))[1])] : s->root_level; + solver_canceluntil(s,blevel); + 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 = solver_progress(s); + solver_canceluntil(s,s->root_level); + vec_delete(&learnt_clause); + return l_Undef; } + + if (solver_dlevel(s) == 0) + // Simplify the set of problem clauses: + solver_simplify(s); + + if (nof_learnts >= 0 && vec_size(&s->learnts) - s->qtail >= nof_learnts) + // Reduce the set of learnt clauses: + 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; + for (i = 0; i < s->size; i++) vec_push(&s->model,(void*)((int)values[i])); + solver_canceluntil(s,s->root_level); + vec_delete(&learnt_clause); + return l_True; + } + + assume(s,neg(toLit(next))); + } + } + + return l_Undef; // cannot happen +} + +//================================================================================================= +// External solver functions: + +solver* solver_new(void) +{ + solver* s = (solver*)malloc(sizeof(solver)); + + // initialize vectors + vec_new(&s->clauses); + vec_new(&s->learnts); + vec_new(&s->order); + vec_new(&s->trail_lim); + vec_new(&s->tagged); + vec_new(&s->stack); + vec_new(&s->model); + + // initialize arrays + s->wlists = 0; + s->activity = 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; + + return s; +} + + +void solver_delete(solver* s) +{ + int i; + for (i = 0; i < vec_size(&s->clauses); i++) + free(vec_begin(&s->clauses)[i]); + + for (i = 0; i < vec_size(&s->learnts); i++) + free(vec_begin(&s->learnts)[i]); + + // delete vectors + vec_delete(&s->clauses); + vec_delete(&s->learnts); + vec_delete(&s->order); + vec_delete(&s->trail_lim); + vec_delete(&s->tagged); + vec_delete(&s->stack); + vec_delete(&s->model); + free(s->binary); + + // delete arrays + if (s->wlists != 0){ + int i; + for (i = 0; i < s->size*2; i++) + vec_delete(&s->wlists[i]); + + // if one is different from null, all are + free(s->wlists); + free(s->activity ); + free(s->assigns ); + free(s->orderpos ); + free(s->reasons ); + free(s->levels ); + free(s->trail ); + free(s->tags ); + } + + free(s); +} + + +bool solver_addclause(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; + } + solver_setnvars(s,maxvar+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 == 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; + else if (j - begin == 1) // unit clause + return enqueue(s,*begin,(clause*)0); + + // create new clause + vec_push(&s->clauses,clause_new(s,begin,j,0)); + + + s->stats.clauses++; + s->stats.clauses_literals += j - begin; + + return true; +} + + +bool solver_simplify(solver* s) +{ + clause** reasons; + int type; + + assert(solver_dlevel(s) == 0); + + if (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++){ + vec* cs = type ? &s->learnts : &s->clauses; + clause** cls = (clause**)vec_begin(cs); + + int i, j; + for (j = i = 0; i < vec_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]; + } + vec_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; +} + + +bool solver_solve(solver* s, lit* begin, lit* end) +{ + double nof_conflicts = 100; + double nof_learnts = solver_nclauses(s) / 3; + lbool status = l_Undef; + lbool* values = s->assigns; + lit* i; + + for (i = begin; i < end; i++) + if ((lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]) == l_False || (assume(s,*i), solver_propagate(s) != 0)){ + solver_canceluntil(s,0); + return false; } + + s->root_level = 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 = solver_search(s,(int)nof_conflicts, (int)nof_learnts); + nof_conflicts *= 1.5; + nof_learnts *= 1.1; + } + if (s->verbosity >= 1) + printf("==============================================================================\n"); + + solver_canceluntil(s,0); + return status != l_False; +} + + +int solver_nvars(solver* s) +{ + return s->size; +} + + +int solver_nclauses(solver* s) +{ + return vec_size(&s->clauses); +} + +//================================================================================================= +// 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 sort(void** array, int size, int(*comp)(const void *, const void *)) +{ + double seed = 91648253; + sortrnd(array,size,comp,&seed); +} diff --git a/src/sat/asat/solver.h b/src/sat/asat/solver.h new file mode 100644 index 00000000..e04d5780 --- /dev/null +++ b/src/sat/asat/solver.h @@ -0,0 +1,137 @@ +/************************************************************************************************** +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 solver_h +#define solver_h + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +#include "solver_vec.h" + +//================================================================================================= +// Simple types: + +//typedef int bool; +#ifndef bool +#define bool int +#endif + +static const bool true = 1; +static const bool false = 0; + +typedef int lit; +typedef char lbool; + +#ifdef _WIN32 +typedef signed __int64 uint64; // compatible with MS VS 6.0 +#else +typedef unsigned long long uint64; +#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 neg (lit l) { return l ^ 1; } +static inline lit toLit (int v) { return v + v; } + +//================================================================================================= +// Public interface: + +struct solver_t; +typedef struct solver_t solver; + +extern solver* solver_new(void); +extern void solver_delete(solver* s); + +extern bool solver_addclause(solver* s, lit* begin, lit* end); +extern bool solver_simplify(solver* s); +extern bool solver_solve(solver* s, lit* begin, lit* end); + +extern int solver_nvars(solver* s); +extern int solver_nclauses(solver* s); + +// additional procedures +extern void Asat_SolverWriteDimacs( solver * pSat, char * pFileName ); + +struct stats_t +{ + uint64 starts, decisions, propagations, inspects, conflicts; + uint64 clauses, clauses_literals, learnts, learnts_literals, max_literals, tot_literals; +}; +typedef struct stats_t stats; + +//================================================================================================= +// Solver representation: + +struct clause_t; +typedef struct clause_t clause; + +struct solver_t +{ + int size; // nof variables + int cap; // size of varmaps + int qhead; // Head index of queue. + int qtail; // Tail index of queue. + + // clauses + vec clauses; // List of problem constraints. (contains: clause*) + vec 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. + + vec* 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; // + vec tagged; // (contains: var) + vec stack; // (contains: var) + + vec order; // Variable order. (heap) (contains: var) + vec trail_lim; // Separator indices for different decision levels in 'trail'. (contains: int) + vec 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; +}; + +#endif diff --git a/src/sat/asat/solver_vec.h b/src/sat/asat/solver_vec.h new file mode 100644 index 00000000..fae313d0 --- /dev/null +++ b/src/sat/asat/solver_vec.h @@ -0,0 +1,53 @@ +/************************************************************************************************** +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 vec_h +#define vec_h + +#include + +struct vec_t { + int size; + int cap; + void** ptr; +}; +typedef struct vec_t vec; + +static inline void vec_new (vec* v) { + v->size = 0; + v->cap = 4; + v->ptr = (void**)malloc(sizeof(void*)*v->cap); +} + +static inline void vec_delete (vec* v) { free(v->ptr); } +static inline void** vec_begin (vec* v) { return v->ptr; } +static inline int vec_size (vec* v) { return v->size; } +static inline void vec_resize (vec* v, int k) { v->size = k; } // only safe to shrink !! +static inline void vec_push (vec* 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/bsat/module.make b/src/sat/bsat/module.make deleted file mode 100644 index 1e52cc0a..00000000 --- a/src/sat/bsat/module.make +++ /dev/null @@ -1,7 +0,0 @@ -SRC += src/sat/bsat/satMem.c \ - src/sat/bsat/satInter.c \ - src/sat/bsat/satInterA.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 8e07e9f6..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_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/satInterA.c b/src/sat/bsat/satInterA.c deleted file mode 100644 index 513a9044..00000000 --- a/src/sat/bsat/satInterA.c +++ /dev/null @@ -1,970 +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" -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// variable assignments -static const lit LIT_UNDEF = 0xffffffff; - -// interpolation manager -struct Inta_Man_t_ -{ - // clauses of the problems - Sto_Man_t * pCnf; // the set of CNF clauses for A and B - Vec_Int_t * vVarsAB; // the array of global variables - // 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 - Aig_Man_t * pAig; // the AIG manager for recording the interpolant - int * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] - Aig_Obj_t ** pInters; // storage for interpolants as truth tables (size nClauses) - int nIntersAlloc; // the allocated size of truth table array - // 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 Aig_Obj_t ** Inta_ManAigRead( Inta_Man_t * pMan, Sto_Cls_t * pCls ) { return pMan->pInters + pCls->Id; } -static inline void Inta_ManAigClear( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst0(pMan->pAig); } -static inline void Inta_ManAigFill( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst1(pMan->pAig); } -static inline void Inta_ManAigCopy( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = *q; } -static inline void Inta_ManAigAnd( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_And(pMan->pAig, *p, *q); } -static inline void Inta_ManAigOr( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, *q); } -static inline void Inta_ManAigOrNot( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(*q)); } -static inline void Inta_ManAigOrVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_IthVar(pMan->pAig, v)); } -static inline void Inta_ManAigOrNotVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(Aig_IthVar(pMan->pAig, v))); } - -// reading/writing the proof for a clause -static inline int Inta_ManProofGet( Inta_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } -static inline void Inta_ManProofSet( Inta_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocate proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Inta_Man_t * Inta_ManAlloc() -{ - Inta_Man_t * p; - // allocate the manager - p = (Inta_Man_t *)malloc( sizeof(Inta_Man_t) ); - memset( p, 0, sizeof(Inta_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 Inta_ManGlobalVars( Inta_Man_t * p ) -{ - Sto_Cls_t * pClause; - int LargeNum = -100000000; - 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] = LargeNum; - } - } - } - assert( nVarsAB <= Vec_IntSize(p->vVarsAB) ); - - // order global variables - nVarsAB = 0; - Vec_IntForEachEntry( p->vVarsAB, Var, v ) - p->pVarTypes[Var] = -(1+nVarsAB++); - - // check that there is no extra global variables - for ( v = 0; v < p->pCnf->nVars; v++ ) - assert( p->pVarTypes[v] != LargeNum ); - return nVarsAB; -} - -/**Function************************************************************* - - Synopsis [Resize proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inta_ManResize( Inta_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 = (int *) realloc( p->pVarTypes, sizeof(int) * 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(int) * 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 - Inta_ManGlobalVars( p ); - - // 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->pCnf->nClauses ) - { - p->nIntersAlloc = p->pCnf->nClauses; - p->pInters = (Aig_Obj_t **) realloc( p->pInters, sizeof(Aig_Obj_t *) * p->nIntersAlloc ); - } - memset( p->pInters, 0, sizeof(Aig_Obj_t *) * p->pCnf->nClauses ); -} - -/**Function************************************************************* - - Synopsis [Deallocate proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inta_ManFree( Inta_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 Inta_ManPrintClause( Inta_Man_t * p, Sto_Cls_t * pClause ) -{ - int i; - printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Inta_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 Inta_ManPrintResolvent( lit * pResLits, int nResLits ) -{ - int i; - printf( "Resolvent: {" ); - for ( i = 0; i < nResLits; i++ ) - printf( " %d", pResLits[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints the interpolant for one clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inta_ManPrintInterOne( Inta_Man_t * p, Sto_Cls_t * pClause ) -{ - printf( "Clause %2d : ", pClause->Id ); -// Extra_PrintBinary___( stdout, Inta_ManAigRead(p, pClause), (1 << p->nVarsAB) ); - printf( "\n" ); -} - - - -/**Function************************************************************* - - Synopsis [Adds one clause to the watcher list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Inta_ManWatchClause( Inta_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 Inta_ManEnqueue( Inta_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 Inta_ManCancelUntil( Inta_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 * Inta_ManPropagateOne( Inta_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]) - Inta_ManWatchClause( p, pCur, pCur->pLits[1] ); - break; - } - if ( i < (int)pCur->nLits ) // found new watch - continue; - - // clause is unit - enqueue new implication - if ( Inta_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 * Inta_ManPropagate( Inta_Man_t * p, int Start ) -{ - Sto_Cls_t * pClause; - int i; - int clk = clock(); - for ( i = Start; i < p->nTrailSize; i++ ) - { - pClause = Inta_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 Inta_ManProofWriteOne( Inta_Man_t * p, Sto_Cls_t * pClause ) -{ - Inta_ManProofSet( p, pClause, ++p->Counter ); - - if ( p->fProofWrite ) - { - int v; - fprintf( p->pFile, "%d", Inta_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 Inta_ManProofTraceOne( Inta_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 ) - Inta_ManAigCopy( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pConflict) ); - - // follow the trail backwards - PrevId = Inta_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( Inta_ManProofGet(p, pReason) > 0 ); - p->Counter++; - if ( p->fProofWrite ) - fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Inta_ManProofGet(p, pReason) ); - PrevId = p->Counter; - - if ( p->pCnf->nClausesA ) - { - if ( p->pVarTypes[Var] == 1 ) // var of A - Inta_ManAigOr( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); - else - Inta_ManAigAnd( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); - } - - // resolve the temporary resolvent with the reason clause - if ( p->fProofVerif ) - { - int v1, v2; - if ( fPrint ) - Inta_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 ) - Inta_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 ); - Inta_ManPrintClause( p, pConflict ); - Inta_ManPrintResolvent( p->pResLits, p->nResLits ); - Inta_ManPrintClause( p, pFinal ); - } - } -p->timeTrace += clock() - clk; - - // return the proof pointer - if ( p->pCnf->nClausesA ) - { -// Inta_ManPrintInterOne( p, pFinal ); - } - Inta_ManProofSet( p, pFinal, p->Counter ); - return p->Counter; -} - -/**Function************************************************************* - - Synopsis [Records the proof for one clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inta_ManProofRecordOne( Inta_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 ( !Inta_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) - { - assert( 0 ); // impossible - return 0; - } - - // propagate the assumptions - pConflict = Inta_ManPropagate( p, p->nRootSize ); - if ( pConflict == NULL ) - { - assert( 0 ); // cannot prove - return 0; - } - - // construct the proof - Inta_ManProofTraceOne( p, pConflict, pClause ); - - // undo to the root level - Inta_ManCancelUntil( p, p->nRootSize ); - - // add large clauses to the watched lists - if ( pClause->nLits > 1 ) - { - Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); - Inta_ManWatchClause( p, pClause, pClause->pLits[1] ); - return 1; - } - assert( pClause->nLits == 1 ); - - // if the clause proved is unit, add it and propagate - if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) - { - assert( 0 ); // impossible - return 0; - } - - // propagate the assumption - pConflict = Inta_ManPropagate( p, p->nRootSize ); - if ( pConflict ) - { - // construct the proof - Inta_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 Inta_ManProcessRoots( Inta_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 ) - { - Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); - Inta_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 ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) - { - // detected root level conflict - printf( "Error in Inta_ManProcessRoots(): Detected a root-level conflict too early!\n" ); - assert( 0 ); - return 0; - } - } - - // propagate the root unit clauses - pClause = Inta_ManPropagate( p, 0 ); - if ( pClause ) - { - // detected root level conflict - Inta_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 Inta_ManPrepareInter( Inta_Man_t * p ) -{ - Sto_Cls_t * pClause; - int Var, VarAB, v; - - // set interpolants for root clauses - Sto_ManForEachClauseRoot( p->pCnf, pClause ) - { - if ( !pClause->fA ) // clause of B - { - Inta_ManAigFill( p, Inta_ManAigRead(p, pClause) ); -// Inta_ManPrintInterOne( p, pClause ); - continue; - } - // clause of A - Inta_ManAigClear( p, Inta_ManAigRead(p, pClause) ); - 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 < Vec_IntSize(p->vVarsAB) ); - if ( lit_sign(pClause->pLits[v]) ) // negative var - Inta_ManAigOrNotVar( p, Inta_ManAigRead(p, pClause), VarAB ); - else - Inta_ManAigOrVar( p, Inta_ManAigRead(p, pClause), VarAB ); - } - } -// Inta_ManPrintInterOne( p, pClause ); - } -} - -/**Function************************************************************* - - Synopsis [Computes interpolant for the given CNF.] - - Description [Takes the interpolation manager, the CNF deriving by the SAT - solver, which includes ClausesA, ClausesB, and learned clauses. Additional - arguments are the vector of variables common to AB and the verbosiness flag. - Returns the AIG manager with a single output, containing the interpolant.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose ) -{ - Aig_Man_t * pRes; - 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; - p->vVarsAB = vVarsAB; - p->pAig = pRes = Aig_ManStart( 10000 ); - Aig_IthVar( p->pAig, Vec_IntSize(p->vVarsAB) - 1 ); - - // adjust the manager - Inta_ManResize( p ); - - // prepare the interpolant computation - Inta_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 ) - Inta_ManProofWriteOne( p, pClause ); - - // propagate root level assignments - if ( Inta_ManProcessRoots( p ) ) - { - // if there is no conflict, consider learned clauses - Sto_ManForEachClause( p->pCnf, pClause ) - { - if ( pClause->fRoot ) - continue; - if ( !Inta_ManProofRecordOne( p, pClause ) ) - { - RetValue = 0; - break; - } - } - } - - // stop the proof - if ( p->fProofWrite ) - { - fclose( p->pFile ); - p->pFile = NULL; - } - - if ( fVerbose ) - { - PRT( "Interpo", clock() - clkTotal ); - 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; - } - - Aig_ObjCreatePo( pRes, *Inta_ManAigRead( p, p->pCnf->pTail ) ); - Aig_ManCleanup( pRes ); - - p->pAig = NULL; - return pRes; - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/bsat/satMem.c b/src/sat/bsat/satMem.c deleted file mode 100644 index 7fa1a824..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 "vec.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 22b7a87c..00000000 --- a/src/sat/bsat/satMem.h +++ /dev/null @@ -1,80 +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 -#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 fbc9874d..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 long)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 c1bf32a7..00000000 --- a/src/sat/bsat/satSolver.h +++ /dev/null @@ -1,210 +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)); } -static inline int lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n; } - - -//================================================================================================= -// 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; -}; - -static int sat_solver_var_value( sat_solver* s, int v ) -{ - assert( s->model.ptr != NULL && v < s->size ); - return (int)(s->model.ptr[v] == l_True); -} -static int sat_solver_var_literal( sat_solver* s, int v ) -{ - assert( s->model.ptr != NULL && v < s->size ); - return toLitCond( v, s->model.ptr[v] != l_True ); -} -static void sat_solver_act_var_clear(sat_solver* s) -{ - int i; - for (i = 0; i < s->size; i++) - s->activity[i] = 0.0; - s->var_inc = 1.0; -} - -#endif diff --git a/src/sat/bsat/satStore.c b/src/sat/bsat/satStore.c deleted file mode 100644 index f968162e..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 b66abc8f..00000000 --- a/src/sat/bsat/satStore.h +++ /dev/null @@ -1,146 +0,0 @@ -/**CFile**************************************************************** - - FileName [satStore.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 __SAT_STORE_H__ -#define __SAT_STORE_H__ - -#include "satSolver.h" - -/* - The trace of SAT solving contains the original clauses 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; -// 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; } -*/ - -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 -}; - -// 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(); -extern void Int_ManFree( Int_Man_t * p ); -extern int Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult ); - -/*=== satInterA.c ==========================================================*/ -typedef struct Inta_Man_t_ Inta_Man_t; -extern Inta_Man_t * Inta_ManAlloc(); -extern void Inta_ManFree( Inta_Man_t * p ); -extern void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose ); - -#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 3961cf7e..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 "vec.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 index 5872f5bc..b030caef 100644 --- a/src/sat/csat/csat_apis.c +++ b/src/sat/csat/csat_apis.c @@ -24,11 +24,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -#define ABC_DEFAULT_CONF_LIMIT 0 // limit on conflicts -#define ABC_DEFAULT_IMP_LIMIT 0 // limit on implications - - -struct ABC_ManagerStruct_t +struct CSAT_ManagerStruct_t { // information about the problem stmm_table * tName2Node; // the hash table mapping names to nodes @@ -36,10 +32,9 @@ struct ABC_ManagerStruct_t 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 + int mode; // 0 = baseline; 1 = resource-aware fraiging + Fraig_Params_t Params; // the set of parameters to call FRAIG package // information about the target int nog; // the numbers of gates in the target Vec_Ptr_t * vNodes; // the gates in the target @@ -48,18 +43,16 @@ struct ABC_ManagerStruct_t 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(); +static CSAT_Target_ResultT * CSAT_TargetResAlloc( int nVars ); +static void CSAT_TargetResFree( CSAT_Target_ResultT * p ); +static char * CSAT_GetNodeName( CSAT_Manager mng, Abc_Obj_t * pNode ); // some external procedures +extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes ); extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -73,24 +66,17 @@ extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); SeeAlso [] ***********************************************************************/ -ABC_Manager ABC_InitManager() +CSAT_Manager CSAT_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"); + CSAT_Manager_t * mng; + mng = ALLOC( CSAT_Manager_t, 1 ); + memset( mng, 0, sizeof(CSAT_Manager_t) ); + mng->pNtk = Abc_NtkAlloc( ABC_TYPE_LOGIC, ABC_FUNC_SOP ); + mng->pNtk->pName = util_strsav("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; } @@ -105,52 +91,40 @@ ABC_Manager ABC_InitManager() SeeAlso [] ***********************************************************************/ -void ABC_ReleaseManager( ABC_Manager mng ) +void CSAT_QuitManager( CSAT_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 [] + Description [0 = baseline; 1 = resource-aware solving.] SideEffects [] SeeAlso [] ***********************************************************************/ -void ABC_SetSolveOption( ABC_Manager mng, enum CSAT_OptionT option ) +void CSAT_SetSolveOption( CSAT_Manager mng, enum CSAT_OptionT option ) { + mng->mode = option; + if ( option == 0 ) + printf( "CSAT_SetSolveOption: Setting baseline solving mode.\n" ); + else if ( option == 1 ) + printf( "CSAT_SetSolveOption: Setting resource-aware solving mode.\n" ); + else + printf( "CSAT_SetSolveOption: Unknown option.\n" ); } -/**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************************************************************* @@ -167,24 +141,18 @@ void ABC_UseOnlyCoreSatSolver( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, char ** fanins, int dc_attr ) +int CSAT_AddGate( CSAT_Manager mng, enum GateType type, char * name, int nofi, char ** fanins, int dc_attr ) { Abc_Obj_t * pObj, * pFanin; - char * pSop, * pNewName; + char * pSop; 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; } + { printf( "CSAT_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 ); @@ -204,7 +172,7 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha 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; } + { printf( "CSAT_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[i] ); return 0; } Abc_ObjAddFanin( pObj, pFanin ); } // create the node function @@ -212,51 +180,51 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha { case CSAT_CONST: if ( nofi != 0 ) - { printf( "ABC_AddGate: The constant gate \"%s\" has fanins.\n", name ); return 0; } + { printf( "CSAT_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 ); + { printf( "CSAT_AddGate: The AND gate \"%s\" no fanins.\n", name ); return 0; } + pSop = Abc_SopCreateAnd( mng->pNtk->pManFunc, nofi ); break; case CSAT_BNAND: if ( nofi < 1 ) - { printf( "ABC_AddGate: The NAND gate \"%s\" no fanins.\n", name ); return 0; } + { printf( "CSAT_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; } + { printf( "CSAT_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; } + { printf( "CSAT_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; } + { printf( "CSAT_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; } + { printf( "CSAT_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; } + { printf( "CSAT_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; } + { printf( "CSAT_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; } + { printf( "CSAT_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; } + { printf( "CSAT_AddGate: The buffer gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } pSop = Abc_SopCreateBuf( mng->pNtk->pManFunc ); break; default : @@ -267,85 +235,66 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha 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; } + { printf( "CSAT_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; } + { printf( "CSAT_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" ); + printf( "CSAT_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; } + { printf( "CSAT_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.] + Synopsis [Checks integraty of the manager.] - Description [] + 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 [] ***********************************************************************/ -void ABC_Network_Finalize( ABC_Manager mng ) +int CSAT_Check_Integrity( CSAT_Manager mng ) { Abc_Ntk_t * pNtk = mng->pNtk; Abc_Obj_t * pObj; int i; + + // this procedure also finalizes construction of the ABC network + Abc_NtkFixNonDrivenNets( pNtk ); Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL ); + Abc_NtkLogicStoreName( pObj, CSAT_GetNodeName(mng, pObj) ); Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL ); + Abc_NtkLogicStoreName( pObj, CSAT_GetNodeName(mng, pObj) ); 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; + // make sure everything is okay with the network structure + if ( !Abc_NtkCheckRead( pNtk ) ) + { + printf( "CSAT_Check_Integrity: The internal network check has failed.\n" ); + return 0; + } - // check that there are no dangling nodes + // check that there is 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" ); + printf( "CSAT_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; } @@ -360,9 +309,9 @@ int ABC_Check_Integrity( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -void ABC_SetTimeLimit( ABC_Manager mng, int runtime ) +void CSAT_SetTimeLimit( CSAT_Manager mng, int runtime ) { -// printf( "ABC_SetTimeLimit: The resource limit is not implemented (warning).\n" ); + printf( "CSAT_SetTimeLimit: The resource limit is not implemented (warning).\n" ); } /**Function************************************************************* @@ -376,9 +325,9 @@ void ABC_SetTimeLimit( ABC_Manager mng, int runtime ) SeeAlso [] ***********************************************************************/ -void ABC_SetLearnLimit( ABC_Manager mng, int num ) +void CSAT_SetLearnLimit( CSAT_Manager mng, int num ) { -// printf( "ABC_SetLearnLimit: The resource limit is not implemented (warning).\n" ); + printf( "CSAT_SetLearnLimit: The resource limit is not implemented (warning).\n" ); } /**Function************************************************************* @@ -392,9 +341,9 @@ void ABC_SetLearnLimit( ABC_Manager mng, int num ) SeeAlso [] ***********************************************************************/ -void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num ) +void CSAT_SetSolveBacktrackLimit( CSAT_Manager mng, int num ) { -// printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" ); + printf( "CSAT_SetSolveBacktrackLimit: The resource limit is not implemented (warning).\n" ); } /**Function************************************************************* @@ -408,88 +357,9 @@ void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num ) SeeAlso [] ***********************************************************************/ -void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num ) +void CSAT_SetLearnBacktrackLimit( CSAT_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; + printf( "CSAT_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" ); } /**Function************************************************************* @@ -503,10 +373,10 @@ uint64 ABC_GetTotalInspectsMade( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -void ABC_EnableDump( ABC_Manager mng, char * dump_file ) +void CSAT_EnableDump( CSAT_Manager mng, char * dump_file ) { FREE( mng->pDumpFileName ); - mng->pDumpFileName = Extra_UtilStrsav( dump_file ); + mng->pDumpFileName = util_strsav( dump_file ); } /**Function************************************************************* @@ -524,12 +394,12 @@ void ABC_EnableDump( ABC_Manager mng, char * dump_file ) SeeAlso [] ***********************************************************************/ -int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values ) +int CSAT_AddTarget( CSAT_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; } + { printf( "CSAT_AddTarget: The target has no gates.\n" ); return 0; } // clear storage for the target mng->nog = 0; Vec_PtrClear( mng->vNodes ); @@ -538,10 +408,10 @@ int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values ) 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; } + { printf( "CSAT_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; } + { printf( "CSAT_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; @@ -553,26 +423,50 @@ int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values ) Synopsis [Initialize the solver internal data structure.] Description [Prepares the solver to work on one specific target - set by calling ABC_AddTarget before.] + set by calling CSAT_AddTarget before.] SideEffects [] SeeAlso [] ***********************************************************************/ -void ABC_SolveInit( ABC_Manager mng ) +void CSAT_SolveInit( CSAT_Manager mng ) { + Fraig_Params_t * pParams = &mng->Params; + int nWords1, nWords2, nWordsMin; + // 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; } + { printf( "CSAT_SolveInit: Target is not specified by CSAT_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 ); + mng->pTarget = Abc_NtkCreateCone( mng->pNtk, mng->vNodes, mng->vValues ); + + // 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(mng->pTarget) + Abc_NtkCiNum(mng->pTarget)); + nWordsMin = ABC_MIN( nWords1, nWords2 ); + + // set parameters for fraiging + memset( pParams, 0, sizeof(Fraig_Params_t) ); + 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 = 99; // the max number of backtracks to perform at a node + pParams->fFuncRed = mng->mode; // 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 verbosiness flag for proof reporting } /**Function************************************************************* @@ -586,13 +480,13 @@ void ABC_SolveInit( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -void ABC_AnalyzeTargets( ABC_Manager mng ) +void CSAT_AnalyzeTargets( CSAT_Manager mng ) { } /**Function************************************************************* - Synopsis [Solves the targets added by ABC_AddTarget().] + Synopsis [Solves the targets added by CSAT_AddTarget().] Description [] @@ -601,24 +495,23 @@ void ABC_AnalyzeTargets( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) +enum CSAT_StatusT CSAT_Solve( CSAT_Manager mng ) { - Prove_Params_t * pParams = &mng->Params; + Fraig_Man_t * pMan; + int * pModel; 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; } + { printf( "CSAT_Solve: Target network is not derived by CSAT_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 + // transform the target into a fraig + pMan = Abc_NtkToFraig( mng->pTarget, &mng->Params, 0 ); + Fraig_ManProveMiter( pMan ); // analyze the result - mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); + mng->pResult = CSAT_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); + RetValue = Fraig_ManCheckMiter( pMan ); if ( RetValue == -1 ) mng->pResult->status = UNDETERMINED; else if ( RetValue == 1 ) @@ -626,16 +519,20 @@ enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) else if ( RetValue == 0 ) { mng->pResult->status = SATISFIABLE; + pModel = Fraig_ManReadModel( pMan ); + assert( pModel != NULL ); // 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]; + mng->pResult->names[i] = CSAT_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)); // returns the same string that was given + mng->pResult->values[i] = pModel[i]; } - FREE( mng->pTarget->pModel ); } - else assert( 0 ); + else + assert( 0 ); + // delete the fraig manager + Fraig_ManFree( pMan ); // delete the target Abc_NtkDelete( mng->pTarget ); mng->pTarget = NULL; @@ -647,40 +544,38 @@ enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) Synopsis [Gets the solve status of a target.] - Description [TargetID: the target id returned by ABC_AddTarget().] + Description [TargetID: the target id returned by CSAT_AddTarget().] SideEffects [] SeeAlso [] ***********************************************************************/ -CSAT_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID ) +CSAT_Target_ResultT * CSAT_Get_Target_Result( CSAT_Manager mng, int TargetID ) { return mng->pResult; } /**Function************************************************************* - Synopsis [Dumps the original network into the BENCH file.] + Synopsis [Dumps the target AIG into the BENCH file.] - Description [This procedure should be modified to dump the target.] + Description [] SideEffects [] - SeeAlso [] + SeeAlso [] ***********************************************************************/ -void ABC_Dump_Bench_File( ABC_Manager mng ) +void CSAT_Dump_Bench_File( CSAT_Manager mng ) { - Abc_Ntk_t * pNtkTemp, * pNtkAig; + Abc_Ntk_t * pNtkTemp; char * pFileName; - + // derive the netlist - pNtkAig = Abc_NtkStrash( mng->pNtk, 0, 0, 0 ); - pNtkTemp = Abc_NtkToNetlistBench( pNtkAig ); - Abc_NtkDelete( pNtkAig ); + pNtkTemp = Abc_NtkLogicToNetlistBench( mng->pTarget ); if ( pNtkTemp == NULL ) - { printf( "ABC_Dump_Bench_File: Dumping BENCH has failed.\n" ); return; } + { printf( "CSAT_Dump_Bench_File: Dumping BENCH has failed.\n" ); return; } pFileName = mng->pDumpFileName? mng->pDumpFileName: "abc_test.bench"; Io_WriteBench( pNtkTemp, pFileName ); Abc_NtkDelete( pNtkTemp ); @@ -699,7 +594,7 @@ void ABC_Dump_Bench_File( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars ) +CSAT_Target_ResultT * CSAT_TargetResAlloc( int nVars ) { CSAT_Target_ResultT * p; p = ALLOC( CSAT_Target_ResultT, 1 ); @@ -723,18 +618,10 @@ CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars ) SeeAlso [] ***********************************************************************/ -void ABC_TargetResFree( CSAT_Target_ResultT * p ) +void CSAT_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 ); @@ -751,7 +638,7 @@ void ABC_TargetResFree( CSAT_Target_ResultT * p ) SeeAlso [] ***********************************************************************/ -char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode ) +char * CSAT_GetNodeName( CSAT_Manager mng, Abc_Obj_t * pNode ) { char * pName = NULL; if ( !stmm_lookup( mng->tNode2Name, (char *)pNode, (char **)&pName ) ) @@ -761,7 +648,6 @@ char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode ) return pName; } - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/csat/csat_apis.h b/src/sat/csat/csat_apis.h index b80eddbf..124ca266 100644 --- a/src/sat/csat/csat_apis.h +++ b/src/sat/csat/csat_apis.h @@ -12,16 +12,12 @@ Date [Ver. 1.0. Started - August 28, 2005] - Revision [$Id: csat_apis.h,v 1.5 2005/12/30 10:54:40 rmukherj Exp $] + Revision [$Id: csat_apis.h,v 1.00 2005/08/28 00:00:00 alanmi Exp $] ***********************************************************************/ -#ifndef __ABC_APIS_H__ -#define __ABC_APIS_H__ - -#ifdef __cplusplus -extern "C" { -#endif +#ifndef __CSAT_APIS_H__ +#define __CSAT_APIS_H__ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// @@ -36,44 +32,36 @@ extern "C" { //////////////////////////////////////////////////////////////////////// -typedef struct ABC_ManagerStruct_t ABC_Manager_t; -typedef struct ABC_ManagerStruct_t * ABC_Manager; +typedef struct CSAT_ManagerStruct_t CSAT_Manager_t; +typedef struct CSAT_ManagerStruct_t * CSAT_Manager; // GateType defines the gate type that can be added to circuit by -// ABC_AddGate(); -#ifndef _ABC_GATE_TYPE_ -#define _ABC_GATE_TYPE_ +// CSAT_AddGate(); +#ifndef _CSAT_GATE_TYPE_ +#define _CSAT_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) + 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_BPPO, // bit level PSEUDO PRIMARY OUTPUT + CSAT_BPO // boolean PO }; #endif -//CSAT_StatusT defines the return value by ABC_Solve(); -#ifndef _ABC_STATUS_ -#define _ABC_STATUS_ +//CSAT_StatusT defines the return value by CSAT_Solve(); +#ifndef _CSAT_STATUS_ +#define _CSAT_STATUS_ enum CSAT_StatusT { UNDETERMINED = 0, @@ -88,22 +76,10 @@ enum CSAT_StatusT #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_ +// which is used by CSAT_SetSolveOption(); +#ifndef _CSAT_OPTION_ +#define _CSAT_OPTION_ enum CSAT_OptionT { BASE_LINE = 0, @@ -113,8 +89,8 @@ enum CSAT_OptionT #endif -#ifndef _ABC_Target_Result -#define _ABC_Target_Result +#ifndef _CSAT_Target_Result +#define _CSAT_Target_Result typedef struct _CSAT_Target_ResultT CSAT_Target_ResultT; struct _CSAT_Target_ResultT { @@ -138,21 +114,14 @@ struct _CSAT_Target_ResultT #endif //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// // create a new manager -extern ABC_Manager ABC_InitManager(void); - -// release a manager -extern void ABC_ReleaseManager(ABC_Manager mng); +extern CSAT_Manager CSAT_InitManager(void); // 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); - +extern void CSAT_SetSolveOption(CSAT_Manager mng, enum CSAT_OptionT option); // add a gate to the circuit // the meaning of the parameters are: @@ -160,63 +129,46 @@ extern void ABC_UseOnlyCoreSatSolver(ABC_Manager mng); // 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); +extern int CSAT_AddGate(CSAT_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 ); +extern int CSAT_Check_Integrity(CSAT_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 ); +extern void CSAT_SetTimeLimit(CSAT_Manager mng, int runtime); +extern void CSAT_SetLearnLimit(CSAT_Manager mng, int num); +extern void CSAT_SetSolveBacktrackLimit(CSAT_Manager mng, int num); +extern void CSAT_SetLearnBacktrackLimit(CSAT_Manager mng, int num); +extern void CSAT_EnableDump(CSAT_Manager mng, char* dump_file); // 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); +extern int CSAT_AddTarget(CSAT_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); +extern void CSAT_SolveInit(CSAT_Manager mng); +extern void CSAT_AnalyzeTargets(CSAT_Manager mng); -// solve the targets added by ABC_AddTarget() -extern enum CSAT_StatusT ABC_Solve(ABC_Manager mng); +// solve the targets added by CSAT_AddTarget() +extern enum CSAT_StatusT CSAT_Solve(CSAT_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 +// TargetID: the target id returned by CSAT_AddTarget(). +extern CSAT_Target_ResultT * CSAT_Get_Target_Result(CSAT_Manager mng, int TargetID); +extern void CSAT_Dump_Bench_File(CSAT_Manager mng); //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/sat/fraig/fraig.h b/src/sat/fraig/fraig.h index 1dad21e2..901bbac9 100644 --- a/src/sat/fraig/fraig.h +++ b/src/sat/fraig/fraig.h @@ -18,26 +18,11 @@ #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 /// //////////////////////////////////////////////////////////////////////// @@ -52,14 +37,12 @@ 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 @@ -69,39 +52,6 @@ struct Fraig_ParamsStruct_t_ 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 }; //////////////////////////////////////////////////////////////////////// @@ -109,14 +59,14 @@ struct Prove_ParamsStruct_t_ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // 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))) +#define Fraig_IsComplement(p) (((int)((long) (p) & 01))) +#define Fraig_Regular(p) ((Fraig_Node_t *)((unsigned)(p) & ~01)) +#define Fraig_Not(p) ((Fraig_Node_t *)((long)(p) ^ 01)) +#define Fraig_NotCond(p,c) ((Fraig_Node_t *)((long)(p) ^ (c))) // these are currently not used #define Fraig_Ref(p) @@ -124,7 +74,7 @@ struct Prove_ParamsStruct_t_ #define Fraig_RecursiveDeref(p,c) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== fraigApi.c =============================================================*/ @@ -153,9 +103,6 @@ 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 ); @@ -200,15 +147,10 @@ extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, 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 ); @@ -220,11 +162,10 @@ extern int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pO 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 int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ); +extern int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ); 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 ); @@ -259,9 +200,4 @@ extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fSt //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -} -#endif - #endif diff --git a/src/sat/fraig/fraigApi.c b/src/sat/fraig/fraigApi.c index 79a7c224..b92f6afd 100644 --- a/src/sat/fraig/fraigApi.c +++ b/src/sat/fraig/fraigApi.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -64,12 +64,6 @@ int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ) { 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************************************************************* diff --git a/src/sat/fraig/fraigCanon.c b/src/sat/fraig/fraigCanon.c index 89bc924f..5a7d0563 100644 --- a/src/sat/fraig/fraigCanon.c +++ b/src/sat/fraig/fraigCanon.c @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -49,8 +49,7 @@ 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; + int RetValue; // check for trivial cases if ( p1 == p2 ) @@ -69,7 +68,7 @@ Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_ return p1; return Fraig_Not(pMan->pConst1); } -/* + // check for less trivial cases if ( Fraig_IsComplement(p1) ) { @@ -126,7 +125,7 @@ Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_ return Fraig_Not(pMan->pConst1); } } -*/ + // perform level-one structural hashing if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found { @@ -168,8 +167,7 @@ Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_ // 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 ) ) + if ( Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit ) ) { // 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 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 index 789bffca..b44bacd7 100644 --- a/src/sat/fraig/fraigFanout.c +++ b/src/sat/fraig/fraigFanout.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/fraig/fraigFeed.c b/src/sat/fraig/fraigFeed.c index 8a3cc6c7..73640387 100644 --- a/src/sat/fraig/fraigFeed.c +++ b/src/sat/fraig/fraigFeed.c @@ -37,7 +37,7 @@ static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -463,10 +463,6 @@ Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p ) 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++ ) diff --git a/src/sat/fraig/fraigInt.h b/src/sat/fraig/fraigInt.h index 9c6e0d47..131b750c 100644 --- a/src/sat/fraig/fraigInt.h +++ b/src/sat/fraig/fraigInt.h @@ -47,7 +47,7 @@ */ //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// // enable this macro to support the fanouts @@ -66,7 +66,7 @@ // 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)) +#define FRAIG_NUM_WORDS(n) ((n)/32 + (((n)%32) > 0)) // maximum/minimum operators #define FRAIG_MIN(a,b) (((a) < (b))? (a) : (b)) @@ -143,7 +143,6 @@ struct Fraig_ManStruct_t_ 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 @@ -152,7 +151,6 @@ struct Fraig_ManStruct_t_ 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 @@ -190,8 +188,7 @@ struct Fraig_ManStruct_t_ 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 nSatFails; // the number of times the SAT solver failed to complete int nSatCallsImp; // the number of times equivalence checking was called int nSatProofImp; // the number of times a proof was found @@ -245,9 +242,8 @@ struct Fraig_NodeStruct_t_ 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 + unsigned nOnes : 21; // the number of 1's in the random sim info // the children of the node Fraig_Node_t * p1; // the first child @@ -283,9 +279,9 @@ struct Fraig_NodeStruct_t_ // 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 + int nSize; // the number of entries in the array + int nCap; // the number of allocated entries }; // the hash table @@ -368,7 +364,7 @@ struct Fraig_HashTableStruct_t_ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /*=== fraigCanon.c =============================================================*/ @@ -384,8 +380,6 @@ 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 ); @@ -444,8 +438,8 @@ extern int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig /*=== fraigVec.c ===============================================================*/ extern void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ); -#endif - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/sat/fraig/fraigMan.c b/src/sat/fraig/fraigMan.c index 7fd937d5..e5979c93 100644 --- a/src/sat/fraig/fraigMan.c +++ b/src/sat/fraig/fraigMan.c @@ -26,85 +26,9 @@ int timeSelect; int timeAssign; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// -/**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.] @@ -122,7 +46,6 @@ void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ) 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 @@ -132,39 +55,6 @@ void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ) 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************************************************************* @@ -184,8 +74,7 @@ Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) Fraig_Man_t * p; // set the random seed for simulation -// srand( 0xFEEDDEAF ); - srand( 0xDEADCAFE ); + srand( 0xFEEDDEAF ); // set parameters for equivalence checking if ( pParams == NULL ) @@ -211,7 +100,6 @@ Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) 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) @@ -220,7 +108,6 @@ Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) 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) ); @@ -266,7 +153,7 @@ void Fraig_ManFree( Fraig_Man_t * p ) // Fraig_TablePrintStatsF( p ); // Fraig_TablePrintStatsF0( p ); } - + for ( i = 0; i < p->vNodes->nSize; i++ ) if ( p->vNodes->pArray[i]->vFanins ) { @@ -307,31 +194,6 @@ void Fraig_ManFree( Fraig_Man_t * p ) 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************************************************************* @@ -352,8 +214,8 @@ void Fraig_ManPrintStats( Fraig_Man_t * p ) (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( "Proof = %d. Counter-example = %d. Fail = %d. Zero = %d.\n", + p->nSatProof, p->nSatCounter, p->nSatFails, 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 ); @@ -371,168 +233,6 @@ void Fraig_ManPrintStats( Fraig_Man_t * p ) // 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 index 500431c6..dbf42da4 100644 --- a/src/sat/fraig/fraigMem.c +++ b/src/sat/fraig/fraigMem.c @@ -43,7 +43,7 @@ struct Fraig_MemFixed_t_ }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -201,7 +201,7 @@ void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ) int i; char * pTemp; - // deallocate all chunks except the first one + // delocate all chunks except the first one for ( i = 1; i < p->nChunks; i++ ) free( p->pChunks[i] ); p->nChunks = 1; diff --git a/src/sat/fraig/fraigNode.c b/src/sat/fraig/fraigNode.c index 6e3d3c7d..a6c1d5a6 100644 --- a/src/sat/fraig/fraigNode.c +++ b/src/sat/fraig/fraigNode.c @@ -26,7 +26,7 @@ #define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv) //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -176,7 +176,6 @@ Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_ // 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(); diff --git a/src/sat/fraig/fraigPrime.c b/src/sat/fraig/fraigPrime.c index 127ad478..0f37a586 100644 --- a/src/sat/fraig/fraigPrime.c +++ b/src/sat/fraig/fraigPrime.c @@ -22,7 +22,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -// The 1,024 smallest prime numbers used to compute the hash value +// The 1,000 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, @@ -93,12 +93,10 @@ int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, 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 }; +7877, 7879, 7883, 7901, 7907, 7919 }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** diff --git a/src/sat/fraig/fraigSat.c b/src/sat/fraig/fraigSat.c index 53057fc3..17201e58 100644 --- a/src/sat/fraig/fraigSat.c +++ b/src/sat/fraig/fraigSat.c @@ -17,7 +17,6 @@ ***********************************************************************/ #include "fraigInt.h" -#include "math.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -34,7 +33,6 @@ static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pN 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 ); @@ -43,10 +41,8 @@ extern void * Msat_ClauseVecReadEntry( void * p, int i ); // 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 DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -60,13 +56,13 @@ static int nMuxes; SeeAlso [] ***********************************************************************/ -int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ) +int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ) { if ( pNode1 == pNode2 ) return 1; if ( pNode1 == Fraig_Not(pNode2) ) return 0; - return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit ); + return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit ); } /**Function************************************************************* @@ -99,9 +95,9 @@ void Fraig_ManProveMiter( Fraig_Man_t * p ) // 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_NodeIsEquivalent( p, p->pConst1, pNode, -1 ) ) { - if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ^ Fraig_NodeComparePhase(p->pConst1, pNode) ) + if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ) p->vOutputs->pArray[i] = Fraig_Not(p->pConst1); else p->vOutputs->pArray[i] = p->pConst1; @@ -109,7 +105,7 @@ void Fraig_ManProveMiter( Fraig_Man_t * p ) } if ( p->fVerboseP ) { -// PRT( "Final miter proof time", clock() - clk ); + PRT( "Final miter proof time", clock() - clk ); } } @@ -127,158 +123,26 @@ void Fraig_ManProveMiter( Fraig_Man_t * p ) 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 ) + // get the output node (it can be complemented!) + pNode = p->vOutputs->pArray[0]; + // if the miter is constant 0, the problem is UNSAT + if ( pNode == Fraig_Not(p->pConst1) ) return 1; - // skip the boundary node - if ( pNode->TravId == pMan->nTravIds-1 ) + // consider the special case when the miter is constant 1 + if ( pNode == p->pConst1 ) { - pNode->TravId = pMan->nTravIds; - return 1; - } - pNode->TravId = pMan->nTravIds; - // skip the PI node - if ( pNode->NumPi >= 0 ) + // 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; - // 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? '+':'-' ); + // save the counter example + p->pModel = Fraig_ManSaveCounterExample( p, pNode ); + // if the model is not found, return undecided + if ( p->pModel == NULL ) + return -1; + return 0; } @@ -296,40 +160,34 @@ void Fraig_VarsStudy( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew SeeAlso [] ***********************************************************************/ -int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ) +int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ) { 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 ); + { + extern int timeSelect; + extern int timeAssign; + // 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; + } // 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 ); + Msat_SolverAddVar( p->pSat ); @@ -341,26 +199,17 @@ int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * } */ - 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 ); @@ -371,18 +220,14 @@ if ( fVerbose ) 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 ); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit ); p->timeSat += clock() - clk; if ( RetValue1 == MSAT_FALSE ) @@ -415,31 +260,13 @@ 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++; + p->nSatFails++; return 0; } @@ -459,9 +286,8 @@ p->time3 += clock() - clk; Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); // run the solver clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit ); p->timeSat += clock() - clk; - if ( RetValue1 == MSAT_FALSE ) { //p->time1 += clock() - clk; @@ -493,42 +319,17 @@ 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++; + p->nSatFails++; 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; } @@ -558,12 +359,32 @@ int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t // make sure the solver is allocated and has enough variables if ( p->pSat == NULL ) - Fraig_ManCreateSolver( p ); + { + extern int timeSelect; + extern int timeAssign; + // 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; + } // 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 ); + Msat_SolverAddVar( p->pSat ); + - // get the logic cone +/* + { + 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" ); + } +*/ + + + // get the logic cone clk = clock(); Fraig_OrderVariables( p, pOld, pNew ); // Fraig_PrepareCones( p, pOld, pNew ); @@ -590,7 +411,7 @@ if ( fVerbose ) Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); // run the solver clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit ); p->timeSat += clock() - clk; if ( RetValue1 == MSAT_FALSE ) @@ -622,8 +443,8 @@ if ( fVerbose ) PRT( "time", clock() - clk ); } // record the counter example - Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); - p->nSatCounterImp++; +// Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); +// p->nSatCounterImp++; return 0; } else // if ( RetValue1 == MSAT_UNKNOWN ) @@ -634,96 +455,6 @@ p->time3 += clock() - clk; } } -/**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************************************************************* @@ -755,7 +486,6 @@ void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * Fraig_PrepareCones_rec( pMan, pNew ); Fraig_PrepareCones_rec( pMan, pOld ); - /* nVars = Msat_IntVecReadSize( pMan->vVarsInt ); pVars = Msat_IntVecReadArray( pMan->vVarsInt ); @@ -919,8 +649,6 @@ void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); Fraig_SupergateAddClausesMux( pMan, pNode ); // Fraig_DetectFanoutFreeConeMux( pMan, pNode ); - - nMuxes++; } else { @@ -1255,33 +983,6 @@ void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode ) 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 ); - } @@ -1414,40 +1115,6 @@ printf( "%d(%d)", vFanins->nSize, nCubes ); } - -/**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 index b68bbe0e..d0f22acd 100644 --- a/src/sat/fraig/fraigTable.c +++ b/src/sat/fraig/fraigTable.c @@ -26,7 +26,7 @@ static void Fraig_TableResizeS( Fraig_HashTable_t * p ); static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/fraig/fraigUtil.c b/src/sat/fraig/fraigUtil.c index 342a7111..2155c4a3 100644 --- a/src/sat/fraig/fraigUtil.c +++ b/src/sat/fraig/fraigUtil.c @@ -38,7 +38,7 @@ static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeV static int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/fraig/fraigVec.c b/src/sat/fraig/fraigVec.c index ba3feecd..2e2603b0 100644 --- a/src/sat/fraig/fraigVec.c +++ b/src/sat/fraig/fraigVec.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/msat/msat.h b/src/sat/msat/msat.h index 53353ba6..21ddcb81 100644 --- a/src/sat/msat/msat.h +++ b/src/sat/msat/msat.h @@ -21,10 +21,6 @@ #ifndef __MSAT_H__ #define __MSAT_H__ -#ifdef __cplusplus -extern "C" { -#endif - //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -69,7 +65,7 @@ typedef enum { MSAT_FALSE = -1, MSAT_UNKNOWN = 0, MSAT_TRUE = 1 } Msat_Type_t; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -80,10 +76,10 @@ typedef enum { MSAT_FALSE = -1, MSAT_UNKNOWN = 0, MSAT_TRUE = 1 } Msat_Type_t; 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_SolverAddVar( Msat_Solver_t * p ); 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 ); +extern bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * pVecAssumps, int nBackTrackLimit ); // printing stats, assignments, and clauses extern void Msat_SolverPrintStats( Msat_Solver_t * p ); extern void Msat_SolverPrintAssignment( Msat_Solver_t * p ); @@ -91,20 +87,17 @@ 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 ); @@ -160,13 +153,8 @@ 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 /// //////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/sat/msat/msatActivity.c b/src/sat/msat/msatActivity.c index 1cd795bd..c9a518ce 100644 --- a/src/sat/msat/msatActivity.c +++ b/src/sat/msat/msatActivity.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -45,9 +45,7 @@ void Msat_SolverVarBumpActivity( Msat_Solver_t * p, Msat_Lit_t Lit ) 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 ) + if ( (p->pdActivity[Var] += p->dVarInc) > 1e100 ) Msat_SolverVarRescaleActivity( p ); Msat_OrderUpdate( p->pOrder, Var ); } diff --git a/src/sat/msat/msatClause.c b/src/sat/msat/msatClause.c index 2ba8cd32..dc39bee6 100644 --- a/src/sat/msat/msatClause.c +++ b/src/sat/msat/msatClause.c @@ -36,7 +36,7 @@ struct Msat_Clause_t_ }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -82,10 +82,6 @@ bool Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, bool fLearned, // 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]); @@ -194,7 +190,6 @@ bool Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, bool fLearned, { Msat_SolverVarBumpActivity( p, pLits[i] ); // Msat_SolverVarBumpActivity( p, pLits[i] ); -// p->pFreq[ MSAT_LIT2VAR(pLits[i]) ]++; } } diff --git a/src/sat/msat/msatClauseVec.c b/src/sat/msat/msatClauseVec.c index 04691cf2..7c24619f 100644 --- a/src/sat/msat/msatClauseVec.c +++ b/src/sat/msat/msatClauseVec.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/msat/msatInt.h b/src/sat/msat/msatInt.h index 03903abe..037616f6 100644 --- a/src/sat/msat/msatInt.h +++ b/src/sat/msat/msatInt.h @@ -56,10 +56,10 @@ typedef long long int64; #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)))) + (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num))) #define FREE(obj) \ - ((obj) ? (free((char *)(obj)), (obj) = 0) : 0) + ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) // By default, custom memory management is used // which guarantees constant time allocation/deallocation @@ -119,7 +119,6 @@ struct Msat_Solver_t_ 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. @@ -152,7 +151,6 @@ struct Msat_Solver_t_ 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; @@ -186,7 +184,7 @@ struct Msat_IntVec_t_ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// +/// MACRO DEFITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/msat/msatMem.c b/src/sat/msat/msatMem.c index 30bf4a96..2d178094 100644 --- a/src/sat/msat/msatMem.c +++ b/src/sat/msat/msatMem.c @@ -72,7 +72,7 @@ struct Msat_MmStep_t_ }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -231,7 +231,7 @@ void Msat_MmFixedRestart( Msat_MmFixed_t * p ) int i; char * pTemp; - // deallocate all chunks except the first one + // delocate all chunks except the first one for ( i = 1; i < p->nChunks; i++ ) free( p->pChunks[i] ); p->nChunks = 1; diff --git a/src/sat/msat/msatOrderH.c b/src/sat/msat/msatOrderH.c index 956e7fc6..ca034233 100644 --- a/src/sat/msat/msatOrderH.c +++ b/src/sat/msat/msatOrderH.c @@ -58,7 +58,7 @@ static void Msat_HeapPercolateDown( Msat_Order_t * p, int i ); extern int timeSelect; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/msat/msatOrderJ.c b/src/sat/msat/msatOrderJ.c index 4db7ff7b..6067b40f 100644 --- a/src/sat/msat/msatOrderJ.c +++ b/src/sat/msat/msatOrderJ.c @@ -38,7 +38,7 @@ struct Msat_OrderVar_t_ { Msat_OrderVar_t * pNext; Msat_OrderVar_t * pPrev; - int Num; + int Num; }; // the ring of variables data structure (J-boundary) @@ -82,7 +82,7 @@ extern int timeSelect; extern int timeAssign; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -170,8 +170,7 @@ 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; + int * pVars, nVars, i; // go through all the variables in the boundary Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext ) @@ -189,14 +188,10 @@ int Msat_OrderCheck( Msat_Order_t * p ) if ( Msat_OrderVarIsAssigned(p, pRound[i]) ) break; } -// assert( i != nRound ); -// if ( i == nRound ) -// return 0; - if ( i == nRound ) - Counter++; + assert( i != nRound ); + if ( i != nRound ) + return 0; } - 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, @@ -214,16 +209,16 @@ int Msat_OrderCheck( Msat_Order_t * p ) 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++ ) + for ( i = 0; i < nRound; i++ ) { - if ( !Msat_OrderVarIsUsedInCone(p, pRound[k]) ) + if ( !Msat_OrderVarIsUsedInCone(p, pRound[i]) ) continue; - if ( Msat_OrderVarIsAssigned(p, pRound[k]) ) + if ( Msat_OrderVarIsAssigned(p, pRound[i]) ) break; } -// assert( k == nRound ); -// if ( k != nRound ) -// return 0; + assert( i == nRound ); + if ( i == nRound ) + return 0; } return 1; } @@ -261,7 +256,7 @@ int Msat_OrderVarSelect( Msat_Order_t * p ) Msat_OrderVar_t * pVar, * pNext, * pVarBest; double * pdActs = p->pSat->pdActivity; double dfActBest; -// int clk = clock(); + int clk = clock(); pVarBest = NULL; dfActBest = -1.0; @@ -273,13 +268,12 @@ int Msat_OrderVarSelect( Msat_Order_t * p ) pVarBest = pVar; } } -//timeSelect += clock() - clk; -//timeAssign += clock() - clk; +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) ); @@ -302,7 +296,7 @@ int Msat_OrderVarSelect( Msat_Order_t * p ) void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) { Msat_IntVec_t * vRound; - int i;//, clk = clock(); + int i, clk = clock(); // make sure the variable is in the boundary assert( Var < p->nVarsAlloc ); @@ -322,7 +316,7 @@ void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) continue; Msat_OrderRingAddLast( &p->rVars, &p->pVars[vRound->pArray[i]] ); } -//timeSelect += clock() - clk; +timeSelect += clock() - clk; // Msat_OrderCheck( p ); } @@ -340,7 +334,7 @@ void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ) { Msat_IntVec_t * vRound, * vRound2; - int i, k;//, clk = clock(); + int i, k, clk = clock(); // make sure the variable is not in the boundary assert( Var < p->nVarsAlloc ); @@ -369,7 +363,7 @@ void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ) if ( k == vRound2->nSize ) // there is no assigned vars, delete this one Msat_OrderRingRemove( &p->rVars, &p->pVars[vRound->pArray[i]] ); } -//timeSelect += clock() - clk; +timeSelect += clock() - clk; // Msat_OrderCheck( p ); } @@ -456,7 +450,7 @@ void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * 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; +// pRing->pRoot = pVar->pNext; // delete the node pVar->pPrev->pNext = pVar->pNext; pVar->pNext->pPrev = pVar->pPrev; diff --git a/src/sat/msat/msatQueue.c b/src/sat/msat/msatQueue.c index 5938e042..c12cc75d 100644 --- a/src/sat/msat/msatQueue.c +++ b/src/sat/msat/msatQueue.c @@ -33,7 +33,7 @@ struct Msat_Queue_t_ }; //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/msat/msatRead.c b/src/sat/msat/msatRead.c index 738562ef..b8e585a4 100644 --- a/src/sat/msat/msatRead.c +++ b/src/sat/msat/msatRead.c @@ -27,7 +27,7 @@ static char * Msat_FileRead( FILE * pFile ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/msat/msatSolverApi.c b/src/sat/msat/msatSolverApi.c index ee3507a6..ba506993 100644 --- a/src/sat/msat/msatSolverApi.c +++ b/src/sat/msat/msatSolverApi.c @@ -27,7 +27,7 @@ static void Msat_SolverSetupTruthTables( unsigned uTruths[][2] ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -41,30 +41,27 @@ static void Msat_SolverSetupTruthTables( unsigned uTruths[][2] ); 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_SolverReadVarNum( Msat_Solver_t * p ) { return p->nVars; } +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; } +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; } +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 p->nBackTracks; } +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_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************************************************************* @@ -175,12 +172,8 @@ Msat_Solver_t * Msat_SolverAlloc( int nVarsAlloc, 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->pdActivity[i] = 0; p->pAssigns = ALLOC( int, p->nVarsAlloc ); p->pModel = ALLOC( int, p->nVarsAlloc ); @@ -244,12 +237,8 @@ void Msat_SolverResize( Msat_Solver_t * p, int 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->pdActivity[i] = 0; p->pAssigns = REALLOC( int, p->pAssigns, p->nVarsAlloc ); p->pModel = REALLOC( int, p->pModel, p->nVarsAlloc ); @@ -403,7 +392,6 @@ void Msat_SolverFree( Msat_Solver_t * p ) Msat_ClauseVecFree( p->vLearned ); FREE( p->pdActivity ); - FREE( p->pFactors ); Msat_OrderFree( p->pOrder ); for ( i = 0; i < 2 * p->nVarsAlloc; i++ ) diff --git a/src/sat/msat/msatSolverCore.c b/src/sat/msat/msatSolverCore.c index f9fee73c..b8d9f328 100644 --- a/src/sat/msat/msatSolverCore.c +++ b/src/sat/msat/msatSolverCore.c @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -39,11 +39,10 @@ SeeAlso [] ***********************************************************************/ -bool Msat_SolverAddVar( Msat_Solver_t * p, int Level ) +bool Msat_SolverAddVar( Msat_Solver_t * p ) { if ( p->nVars == p->nVarsAlloc ) Msat_SolverResize( p, 2 * p->nVarsAlloc ); - p->pLevel[p->nVars] = Level; p->nVars++; return 1; } @@ -132,18 +131,14 @@ void Msat_SolverPrintStats( Msat_Solver_t * p ) SeeAlso [] ***********************************************************************/ -bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTrackLimit, int nTimeLimit ) +bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTrackLimit ) { 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; @@ -177,31 +172,11 @@ bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTra 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 ) + if ( nBackTrackLimit > 0 ) 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; } diff --git a/src/sat/msat/msatSolverIo.c b/src/sat/msat/msatSolverIo.c index 05b7f6a9..f17595a7 100644 --- a/src/sat/msat/msatSolverIo.c +++ b/src/sat/msat/msatSolverIo.c @@ -27,7 +27,7 @@ static char * Msat_TimeStamp(); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/msat/msatSolverSearch.c b/src/sat/msat/msatSolverSearch.c index 11a6540c..13a0c403 100644 --- a/src/sat/msat/msatSolverSearch.c +++ b/src/sat/msat/msatSolverSearch.c @@ -31,7 +31,7 @@ static void Msat_SolverAnalyze( Msat_Solver_t * p, Msat_Clause_t * pC static void Msat_SolverReduceDB( Msat_Solver_t * p ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* @@ -534,18 +534,12 @@ Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLi 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 ) { @@ -605,7 +599,7 @@ Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLi Msat_SolverCancelUntil( p, p->nLevelRoot ); return MSAT_UNKNOWN; } - else if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit ) { + else if ( nBackTrackLimit > 0 && nConfs > nBackTrackLimit ) { // Reached bound on number of conflicts: Msat_QueueClear( p->pQueue ); Msat_SolverCancelUntil( p, p->nLevelRoot ); diff --git a/src/sat/msat/msatSort.c b/src/sat/msat/msatSort.c index 3b89d102..2198d303 100644 --- a/src/sat/msat/msatSort.c +++ b/src/sat/msat/msatSort.c @@ -41,7 +41,7 @@ static int irand(double seed, int size) { static void Msat_SolverSort( Msat_Clause_t ** array, int size, double seed ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* diff --git a/src/sat/msat/msatVec.c b/src/sat/msat/msatVec.c index 75f53047..951969cf 100644 --- a/src/sat/msat/msatVec.c +++ b/src/sat/msat/msatVec.c @@ -28,7 +28,7 @@ static int Msat_IntVecSortCompare1( int * pp1, int * pp2 ); static int Msat_IntVecSortCompare2( int * pp1, int * pp2 ); //////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// +/// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* 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